2017-04-20 14 views
5

मैं एक स्ट्रीम का उपयोग कर रहा हूं जो खिड़की को स्क्रॉल करते समय थ्रॉटल किया जाता है।
थ्रॉटलिंग (जब तक स्क्रॉलिंग तक), यह कंसोल के मानों को छोड़ देता है।आरएक्सजेएस - निष्क्रिय होने पर केवल टाइमर शुरू करें?

हालांकि, जब धारा खाली है (उपयोगकर्ता नहीं खिड़की स्क्रॉल है) - मैं एक टाइमर में लात करना चाहते हैं हालांकि -। यदि उपयोगकर्ता फिर से स्क्रॉल शुरू होता है - मुझे लगता है कि टाइमर मूल्यों का उत्सर्जन नहीं करना चाहती।

वर्तमान में मैं यह कर रहा हूँ:

const observable = Rx.Observable.fromEvent(window, 'scroll'); 

    const subscriber = observable 
     .throttleTime(300) 
     .map(() => 'throttle') 
     .merge(Rx.Observable.interval(1000).map(() => 'tick')) 
     .subscribe(
      (x) => { 
      console.log('Next: event!', x); 
      }, 
      (err) => { 
      console.log('Error: %s', err); 
      }, 
     () => { 
      console.log('Completed'); 
      }); 

समस्या यह है कि, स्क्रॉल करते हुए है - मैं देख रहा हूँ दोनों "throttle" और "tick" (मैं केवल "थ्रॉटल" देखना चाहिए) दूसरे से इस बात का

Think पीओवी। नौकरी हमेशा चलनी है। अगर मैं स्क्रॉल करता हूं - वह थ्रॉटल स्क्रॉल - नौकरी का आह्वान करना चाहिए। अगर मैं स्क्रॉल नहीं करता - एक टाइमर को लात मारना चाहिए और नौकरी करना शुरू करना चाहिए। (और यदि उपयोगकर्ता फिर से स्क्रॉल करना शुरू करता है तो रोकता है)।

प्रश्न:
मैं कैसे स्क्रॉल नहीं की एक निष्क्रिय समय के बाद एक टाइमर शुरू कर सकते हैं?

PLNKR

+2

यह कैसे इतने पर एक अच्छा सवाल बनाना है। +1 –

+0

पुन [आपकी अन्य टिप्पणी] (http://stackoverflow.com/questions/41522222/making-a-typing-timer-in-rxjs-tracking-time-spent-typing/41526650?noredirect=1#comment74109988_41526650) : आप स्क्रॉल का उपयोग करने के लिए 'exhaustMap' +' debounceTime' का उपयोग करके इस चाल का उपयोग करके इसे हल कर सकते हैं।मैंने 'स्विचमैप' के साथ यहां क्या किया है क्योंकि हम घटनाओं के विस्फोट के दौरान कुछ नहीं करते हैं और जब स्ट्रीम निष्क्रिय होती है तो काम होता है। दूसरी तरफ, 'स्विचमैप' प्रत्येक बार एक नई स्क्रॉल इवेंट उत्सर्जित होने पर नौकरी (टाइमर) को पुनरारंभ करेगा। – Dorus

उत्तर

2

मैं इस तरह यह करना चाहते हैं:

const scroll$ = Rx.Observable.fromEvent(window, 'scroll') 
    .throttleTime(300 /* ms */) 
    .publish(); 

scroll$.connect(); 

const subscriber = scroll$ 
    .map(() => 'throttle') 
    .race(Rx.Observable.interval(1000).map(() => 'tick')) 
    .take(1) 
    .repeat() 
    .subscribe(
     (x) => { 
      console.log('Next: event!', x); 
     }, 
     (err) => { 
      console.log('Error: %s', err); 
     }, 
     () => { 
      console.log('Completed'); 
     }); 

यह प्रत्यक्ष है कि पहले का उत्सर्जन करता है जो 1s interval या स्क्रॉल घटना है के लिए एक ही सदस्यता के लिए race() ऑपरेटर का उपयोग करता है। इसके ठीक बाद मैं इसे एक और अंतराल के साथ फिर से शुरू करना चाहता हूं इसलिए मैं take(1).repeat() का उपयोग करता हूं।

मुझे कोदोहराए गए सब्सक्रिप्शन के बीच चलने के लिए एक गर्म अवलोकन करने योग्य भी बदलना पड़ा।

आपका अपडेट किया गया डेमो: https://plnkr.co/edit/sWzSm32uoOQ1hOKigo4s?p=preview

+0

क्या मैं पूछ सकता हूं कि 'प्रकाशित()। कनेक्ट()' के बीच क्या अंतर है - जैसा आपने यहां किया था VS 'publ()। Refcount()' {जो 'शेयर()'} –

+0

@ रॉय 'कनेक्ट() है 'प्रति ऑपरेटर नहीं है (यह एक अवलोकन योग्य नहीं है)। यह 'कनेक्ट करने योग्य ऑब्सर्वेबल' वर्ग पर सिर्फ एक विधि है जो 'सदस्यता' लौटाती है जिसे आप "डिस्कनेक्ट" करने के लिए उपयोग कर सकते हैं। यह 'subscribe() 'विधि के समान है जिसे आप ऑपरेटर के साथ चेन कर सकते हैं लेकिन यह' सदस्यता 'भी देता है। इसका मतलब है कि यह केवल ऑपरेटर श्रृंखला के अंत में उपयोग किया जा सकता है। दूसरी तरफ 'refCount() 'एक और अवलोकन योग्य देता है ताकि आप इसे अन्य ऑपरेटरों के साथ श्रृंखलाबद्ध कर सकें। – martin

+0

मार्टिन, आपने इसे कनेक्ट के माध्यम से एक गर्म देखा है। लेकिन अगर मैं इसे '.share() 'में बदलता हूं (जो इसे गर्म करने का एक और तरीका है) - फिर - स्क्रॉल करते समय - ऐसा लगता है कि यह' थ्रॉटल' देरी का सम्मान नहीं करता है। ऐसा क्यों है ? https://plnkr.co/edit/jjWUxbk9fSItLT1U7uiq?p=preview –

3

आप debounceTime का उपयोग स्क्रॉल किए बिना अवधि का पता लगाने के कर सकते हैं।

const scroll = Rx.Observable.fromEvent(window, 'scroll') 
    .throttleTime(300) 
    .mapTo(false); 
const noscroll = Rx.Observable.fromEvent(window, 'scroll') 
    .startWith(0) // init with no scroll. 
    .debounceTime(300) // detect no scroll after 300 ms. 
    .mapTo(true); 
scroll.merge(noscroll) 
    .switchMap(e => e ? Rx.Observable.interval(1000).mapTo("Tick!") : Rx.Observable.of("Scroll!")) 
    // start the interval if there was no scroll. Stop the interval if there was a scroll. 
    .subscribe(updateTimer) 

अपने कोड के साथ एक और समस्या, merge का उपयोग कर कि दोनों स्रोतों सदस्यता ली रखेंगे है बजाय मैं switchMap (mergeMap के भाई) कि भीतर नमूदार हर बार एक नई घटना उत्सर्जित होता है करने के लिए सदस्यता का उपयोग, लेकिन यह भी सदस्यता समाप्त पिछले आंतरिक स्रोत अगर स्रोत से एक और घटना उत्सर्जित की जाती है।

पुन: प्रश्न का "एक और पीओवी" हिस्सा: आप नौकरी के साथ switchMap में Rx.Observable.interval(1000) को प्रतिस्थापित कर सकते हैं। स्क्रॉलिंग नौकरी रद्द/सदस्यता रद्द कर देगी (जैसे उत्सर्जित है), यदि कोई और स्क्रॉलिंग नहीं है, तो नौकरी फिर से शुरू हो जाएगी।

Live demo

+0

उन दो plunkrs (2 दृष्टिकोण) –

+0

देखकर यह बहुत अच्छा लगेगा कि आपके उत्तर के कोड में, जब मैं https://plnkr.co/edit/JX3QCjj6a9sBPM4fivZL?p=preview –

+0

स्क्रॉल करता हूं तो मुझे कोई उत्सर्जन दिखाई नहीं देता :-) [I मुझे लगता है कि मैंने इसे एक से अधिक बार लिखा है) (https://i.imgur.com/HfcsRt5.jpg) –

संबंधित मुद्दे