Rxjs: Observable.combineLatest बनाम Observable.forkJoin


86

बस आश्चर्य है कि Observable.combineLatestऔर के बीच अंतर क्या है Observable.forkJoin? जहां तक ​​मैं देख सकता हूं, एकमात्र अंतर यह forkJoinहै कि ऑब्जर्वबल्स को पूरा करने की उम्मीद है, जबकि combineLatestनवीनतम मान लौटाएंगे।


4
नोट: rxjs6 + में ये अब बस combineLatest()और forkJoin()कार्य हैं जो एक अवलोकन योग्य बनाते हैं। वे ऐसा ही करते हैं, लेकिन वाक्यविन्यास अलग है। भ्रमित न करें combineLatest, rxjs/operatorsजो 'पाइप करने योग्य' ऑपरेटर है। यदि आप गलत आयात करते हैं तो आपको त्रुटियाँ मिलेंगी।
सिमोन_विवर

जवाबों:


129

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

इसके विपरीत, combineLatestएक ऑब्जर्वेबल रिटर्न देता है जो हर बार इनपुट वेधशालाओं में एक नया मूल्य पैदा करता है, एक बार सभी इनपुट वेधशालाएं कम से कम एक मूल्य का उत्पादन करती हैं। इसका मतलब यह है कि इसमें अनंत मूल्य हो सकते हैं और पूरे नहीं हो सकते। इसका यह भी अर्थ है कि मूल्य के उत्पादन से पहले इनपुट वेधशालाओं को पूरा नहीं करना है।


@GregL एक ऐसा फंक्शन है जो forkJoin की तरह काम करता है लेकिन क्या फेल http कॉल के साथ भी काम करेगा?
तपाकन

2
@Tukkan, मैं एक ऐसे ऑपरेटर की श्रृंखला बनाऊंगा जो त्रुटियों से प्रत्येक http के अवलोकन योग्य हो जाता है, ताकि आप त्रुटि पर प्रत्येक अनुरोध के लिए उपयोग करने के लिए मूल्य (ओं) को परिभाषित करें, बजाय एक ऑपरेटर की तलाश में जो कई वेधशालाओं को मिलाएगा जो त्रुटि हो सकती है (I यकीन नहीं होता कि ऐसा ऑपरेटर मौजूद है)। त्रुटियों से उबरने वाले ऑपरेटरों में शामिल हैं .catch(), .onErrorResumeNext()और संभवतः .retry()(यदि एचटीपी कॉल रुक-रुक कर विफल हो सकती है)।
ग्रेग

1
बस स्पष्ट करने के लिए, वे दोनों सरणियाँ उत्पन्न करते हैं।
साइमन_वेयेर

@Simon_Weaver जरूरी नहीं है। के मामले में combineLatest(), आप इनपुट वेधशालाओं से नवीनतम मानों से आउटपुट मान का उत्पादन करने के तरीके के लिए एक प्रक्षेपण फ़ंक्शन की आपूर्ति कर सकते हैं। डिफ़ॉल्ट रूप से, यदि आप एक निर्दिष्ट नहीं करते हैं, तो आपको उत्सर्जित नवीनतम मानों का एक सरणी मिलेगा।
ग्रेग

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

14

इसके अलावा:

CombLLestest (...) अनुक्रम में वेधशाला चलाता है, एक-एक करके

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

// partial source of static combineLatest (uses the rxjs/operators combineLatest internally):
// If you're using typescript then the output array will be strongly typed based on type inference
return function (source) { return source.lift.call(from_1.from([source].concat(observables)), 
                           new combineLatest_1.CombineLatestOperator(project)); };

forkJoin (...) समानांतर में एक ही समय में वेधशाला चलाता है

यदि आपके पास 3 स्रोत वेधशालाएं हैं, और वे प्रत्येक चलाने में 5 सेकंड लेते हैं तो इसे चलाने में 15 सेकंड लगेंगे combineLatest। जबकि forkJoinवे समानांतर में निष्पादित करते हैं इसलिए 5 सेकंड लगेंगे।

इसलिए forkJoinकुछ और काम करता है, Promise.all(...)जहां आदेश लागू नहीं किया गया है।

त्रुटि से निपटने के लिए विचार:

यदि किसी भी वेधशाला में त्रुटि हुई है - combineLatestतो बाद वाले को निष्पादित नहीं किया जाएगा, लेकिन forkJoinवे सभी चल रहे हैं। तो combineLatestवेधशालाओं के एक 'अनुक्रम' को निष्पादित करने और सभी को एक साथ परिणाम एकत्र करने के लिए उपयोगी हो सकता है।


उन्नत नोट: यदि स्रोत वेधशालाएं पहले से ही 'चल रही हैं' (कुछ और द्वारा सदस्यता ली गई हैं) और आप shareउन पर उपयोग कर रहे हैं - तो आप इस व्यवहार को नहीं देखेंगे।

और भी अधिक उन्नत नोट: CombineLatest आपको हमेशा प्रत्येक स्रोत से नवीनतम देगा, इसलिए यदि कोई स्रोत वेधशाला एक से अधिक मानों का उत्सर्जन करता है तो आपको नवीनतम मिलेगा। यह सिर्फ प्रत्येक स्रोत के लिए एक ही मूल्य नहीं है और अगले पर चलते हैं। यदि आपको यह सुनिश्चित करने की आवश्यकता है कि आप केवल प्रत्येक स्रोत के लिए 'अगली उपलब्ध वस्तु' प्राप्त कर सकते हैं, तो आप स्रोत को अवलोकन योग्य जोड़ सकते हैं .pipe(take(1))जैसा कि आप इसे इनपुट सरणी में जोड़ते हैं।


त्रुटि से निपटने के लिए धन्यवाद धन्यवाद। कई वेधशालाओं के मामले में समझने में त्रुटि से निपटने में काफी मुश्किल है।
डी देशमान

2
मेरा मानना है कि आप गलत व्याख्या की है क्या concat()में combineLatest()कोड कर रही है। यह मुझे Array.prototype.concatविधि की तरह लगता है , RxJS concatविधि की तरह नहीं । यह मानते हुए कि मैं सही हूं, तो यह उत्तर भ्रामक और गलत है, क्योंकि combineLatest()वे एक-एक करके वेधशालाओं को क्रम से निष्पादित नहीं करते हैं। यह उन्हें समानांतर, उसी तरह निष्पादित करता है forkJoin()। अंतर यह है कि कितने मूल्यों का उत्पादन किया जाता है और यदि स्रोत वेधशालाओं को पूरा करना है या नहीं।
ग्रेग

@GregL Array.concat वेधशालाओं के साथ निरर्थक है। मैं बिल्कुल समवर्ती प्रकृति पर निर्भर करता हूं - समझने की महत्वपूर्ण बात यह है कि जब तक वे सभी निष्पादित नहीं हो जाते, तब तक आपको कोई आउटपुट मान नहीं मिलता है।
सिमोन_विवर

मैं आपके द्वारा पोस्ट किए गए नमूना स्रोत कोड में इस कोड का उल्लेख कर रहा था: [source].concat(observables)यह मानते हुए कि आपके कहने का मतलब क्या है जब " combineLatestआंतरिक रूप से उपयोग करता है concat"। मुझे ऐसा लगता है जैसे आप RxJS कॉनैट के साथ एरे कॉनसैट को भ्रमित कर रहे हैं। उत्तरार्द्ध वास्तव में इनपुट वेधशालाओं को अनुक्रम में निष्पादित करता है, जब तक कि प्रत्येक पूरा नहीं हो जाता। लेकिन इसका उपयोग नहीं किया जाता है combineLatest(), यह पूरी तरह से एक अलग ऑपरेटर है।
ग्रेग

3
मेरा मानना ​​है combineLatest()और forkJoin()दोनों समानांतर चलते हैं। दोनों के लिए लगभग 5000 आउटपुट के नीचे कोड चल रहा है। const start = new Date().getTime(); combineLatest([of(null).pipe(delay(5000)), of(null).pipe(delay(5000)), of(null).pipe(delay(5000))]).subscribe(() => console.log(new Date().getTime() - start)); forkJoin([of(null).pipe(delay(5000)), of(null).pipe(delay(5000)), of(null).pipe(delay(5000))]).subscribe(() => console.log(new Date().getTime() - start));
जेरेमी

13

forkJoin - जब सभी वेधशालाएं पूरी हो जाती हैं, तो प्रत्येक से अंतिम उत्सर्जित मूल्य का उत्सर्जन करें।

CombLLestest - जब कोई भी ऑब्ज़र्वेबल एक मान का उत्सर्जन करता है, तो प्रत्येक से नवीनतम मान का उत्सर्जन करें।

उपयोग बहुत समान है, लेकिन आप forkJoin के विपरीत CombLatest से सदस्यता समाप्त करना न भूलें ।


1
अगर एक अगर अनुरोध विफल हो जाता है तो सभी नेस्टेड अनुरोध स्वचालित रूप से रद्द हो जाते हैं, मैं इसे कैसे हल कर सकता हूं?
सुनील गर्ग

1
यदि आप केवल सभी परिणाम प्राप्त करना चाहते हैं तो @SunilGarg आपको forkJoin या CombLatest का उपयोग करना चाहिए। यदि आपको सभी परिणामों की परवाह नहीं है तो आपको अलग से सदस्यता का उपयोग करना चाहिए।
दिमित्री ग्रिन्को

क्या आप इसका जवाब दे सकते हैं stackoverflow.com/questions/55558277/...
सुनील गर्ग

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