सेटटाइमआउट () मेरे ऐप को आकर्षक क्यों बनाता है, लेकिन Rxjs टाइमर ()। Subscribe (…) नहीं करता है?


9

मेरे पास एक घटक है, जो "आलसी लोड" कुछ टिप्पणी करता है, 100ms के अंतराल पर।

जब मैं सेटटाइमआउट का उपयोग करता हूं, तो यह वास्तव में पिछड़ जाता है।

अंग

<div *ngFor="let post of posts">
   <app-post [post]="post" ></app-post>
</div>

इससे मेरा एप्लिकेशन शिथिल हो जाता है (avg fps 14, निष्क्रिय समय 51100ms):

while(this.postService.hasPosts()){
  setTimeout(()=> {
   this.posts.push(this.postService.next(10));
  },100);
}

यह मेरे आवेदन को सुचारू बनाता है (avg fps 35, निष्क्रिय समय 40800ms)

while(this.postService.hasPosts()){
  timer(100).subscribe(()=> {
    this.posts.push(this.postService.next(10));
  });
}

क्या कोई स्पष्टीकरण है, क्यों rxjs टाइमर, बेहतर काम करता है?

मैंने फ़ायरफ़ॉक्स के साथ एक रनटाइम विश्लेषण किया। पहले उदाहरण में, फ्रेम दर 14 एफपीएस पर गिरती है, दूसरे उदाहरण में, 35 एफपीएस।

यहां तक ​​कि निष्क्रिय समय 20% कम है।

यह तरीका और भी आसान है (avg fps 45, निष्क्रिय समय 13500ms):

interval(100).pipe(takeWhile(this.postService.hasPosts()).subscribe(()=> {
    this.posts.push(this.postService.next(10));
  });
}

जवाबों:


2

आपका अंतिम समाधान एकमात्र सही है।

अन्य दो समाधानों की तरह काम नहीं करना चाहिए जैसे आपने उनसे काम करने की अपेक्षा की थी। वास्तव में, इसका परिणाम एक अनंत लूप में होना चाहिए।

इसका कारण यह है कि जावास्क्रिप्ट का ईवेंटलूप कैसे काम करता है। निम्न चित्र जावास्क्रिप्ट रनटाइम का एक मॉडल दिखाता है (छवि यहां से ली गई थी ):

यहां छवि विवरण दर्ज करें

हमारे लिए प्रासंगिक भाग हैं stackऔर queue। एक जावास्क्रिप्ट रनटाइम संदेशों को संसाधित करता है queue। प्रत्येक संदेश एक फ़ंक्शन से जुड़ा होता है जिसे संदेश संसाधित होने के रूप में कहा जाता है।

स्टैक के लिए, प्रत्येक फ़ंक्शन कॉल स्टैक पर एक फ्रेम बनाता है जिसमें फ़ंक्शन तर्क और स्थानीय चर होते हैं। यदि कोई फ़ंक्शन दूसरे फ़ंक्शन को कॉल करता है, तो स्टैक के शीर्ष पर एक नया फ़्रेम धक्का दिया जाता है। जब कोई फ़ंक्शन देता है तो शीर्ष फ़्रेम स्टैक से बाहर पॉप किया जाता है।

अब यदि स्टैक खाली है तो जावास्क्रिप्ट रनटाइम अगले संदेश को queue(सबसे पुराना) पर प्रोसेस करेगा ।

यदि आप उपयोग करते हैं setTimeout(() => doSomething(),100), तो doSomething()फ़ंक्शन 100 मिलीसेकंड के बाद कतार में जुड़ जाता है। यही कारण है कि 100 मिलीसेकंड एक गारंटीकृत समय नहीं बल्कि न्यूनतम समय है। इसलिए आपका doSomething methodकेवल कहा जाता है, यदि स्टैक खाली है और कुछ भी कतार में नहीं है।

लेकिन जब आप थोड़ी देर के लूप में पुनरावृत्ति कर रहे होते हैं और आपकी स्थिति आपके अंदर कोड पर निर्भर करती है setTimeout, तो आपने एक अनंत लूप बनाया है क्योंकि स्टैक खाली नहीं होगा और इसलिए आपका this.posts.push(this.postService.next(10));कोड कभी नहीं कहा जाएगा।

आरएक्सजेएस कार्यान्वयन के लिए भी यही सच है। वे समय को संभालने के लिए अनुसूचियों का उपयोग करते हैं। RxJS में अलग-अलग आंतरिक अनुसूचक कार्यान्वयन हैं, लेकिन जैसा कि हम एक अनुसूचक के लिए कार्यान्वयन में देख सकते हैं intervalऔर timerयदि हम एक अनुसूचक को निर्दिष्ट नहीं करते हैं तो डिफ़ॉल्ट है asyncScheduler। AsyncScheduler अनुसूचियाँ ऊपर बताए गए setIntervalकार्यों की तरह काम करती हैं setTimeout, और कतार पर एक अन्य संदेश देती हैं।

मैंने लूप के साथ आपके दो समाधानों की कोशिश की और वास्तव में पहले ने मेरे ब्राउज़र को पूरी तरह से फ्रीज कर दिया, जबकि दूसरा सुपर लैगी था, लेकिन लूप के अंदर कंसोल के लिए कुछ आउटपुट कर सकता था। मैं वास्तव में नहीं जानता कि दूसरा क्यों थोड़ा अधिक प्रदर्शन करने वाला है, लेकिन फिर भी दोनों वही नहीं हैं जो आप वास्तव में चाहते हैं। आप पहले से ही एक अच्छा समाधान के साथ आए थे और मुझे उम्मीद है कि यह उत्तर आपको यह समझने में मदद कर सकता है कि पहला समाधान इतना बुरा क्यों करता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.