मुझे विशिष्ट साइड इफेक्ट के लिए एक नया सब्सक्रिप्शन कब बनाना चाहिए?


10

पिछले हफ्ते मैंने एक RxJS प्रश्न का उत्तर दिया, जहाँ मैं एक अन्य समुदाय के सदस्य के साथ चर्चा में मिला: "क्या मुझे हर विशिष्ट दुष्प्रभाव के लिए सदस्यता बनानी चाहिए या क्या मुझे सामान्य रूप से सदस्यता कम करने का प्रयास करना चाहिए?" मैं जानना चाहता हूं कि पूर्ण प्रतिक्रियाशील एप्लिकेशन दृष्टिकोण के संदर्भ में मैथोलॉजी का उपयोग क्या करना है या कब एक से दूसरे में स्विच करना है। इससे मुझे और शायद दूसरों को अनैच्छिक चर्चा से बचने में मदद मिलेगी।

सेटअप जानकारी

  • सभी उदाहरण टाइपस्क्रिप्ट में हैं
  • प्रश्न पर बेहतर ध्यान केंद्रित करने के लिए, सदस्यता के लिए जीवनचक्र / निर्माणकर्ताओं के उपयोग और असंबंधित ढांचे में न रखने के लिए
    • कल्पना करें: सब्सक्राइबर को कंस्ट्रक्टर / लाइफसाइकल इनिट में जोड़ा जाता है
    • कल्पना कीजिए: बिना साइकल चलाना जीवनचक्र को नष्ट करने में किया जाता है

एक दुष्प्रभाव (कोणीय नमूना) क्या है

  • UI में अपडेट / इनपुट (उदाहरण के लिए value$ | async)
  • आउटपुट / एक घटक के अपस्ट्रीम (जैसे @Output event = event$)
  • विभिन्न पदानुक्रमों पर विभिन्न सेवाओं के बीच परस्पर क्रिया

अनुकरणीय usecase:

  • दो कार्य: foo: () => void; bar: (arg: any) => void
  • दो स्रोत वेधशाला: http$: Observable<any>; click$: Observable<void>
  • fooके बाद कहा जाता http$है उत्सर्जित और कोई मूल्य की जरूरत है
  • barclick$उत्सर्जन के बाद कहा जाता है , लेकिन वर्तमान मूल्य की जरूरत हैhttp$

केस: हर विशिष्ट साइड इफेक्ट के लिए एक सदस्यता बनाएँ

const foo$ = http$.pipe(
  mapTo(void 0)
);

const bar$ = http$.pipe(
  switchMap(httpValue => click$.pipe(
    mapTo(httpValue)
  )
);

foo$.subscribe(foo);
bar$.subscribe(bar);

केस: सामान्य रूप से सदस्यता कम करें

http$.pipe(
  tap(() => foo()),
  switchMap(httpValue => click$.pipe(
    mapTo(httpValue )
  )
).subscribe(bar);

संक्षेप में मेरी अपनी राय

मैं इस तथ्य को समझ सकता हूं कि सब्सक्राइबर्स आरएक्स लैंडस्केप्स को पहले से अधिक जटिल बनाते हैं, क्योंकि आपको यह सोचना होगा कि सब्सक्राइबर्स को पाइप को कैसे प्रभावित करना चाहिए या उदाहरण के लिए नहीं (अपने अवलोकन योग्य या नहीं साझा करें)। लेकिन जितना अधिक आप अपने कोड को अलग करते हैं (जितना अधिक आप ध्यान केंद्रित करते हैं: क्या होता है) जब भविष्य में आपके कोड को बनाए रखना (परीक्षण, डिबग, अपडेट) करना आसान होता है। इस बात को ध्यान में रखते हुए कि मैं अपने कोड में किसी भी साइड इफेक्ट के लिए हमेशा एक ही ऑब्जर्वेबल सोर्स और सिंगल सब्सक्रिप्शन बनाता हूं। यदि दो या दो से अधिक साइड इफेक्ट्स मुझे ठीक उसी स्रोत के अवलोकन से ट्रिगर होते हैं, तो मैं अपने अवलोकन को साझा करता हूं और प्रत्येक साइड इफेक्ट के लिए व्यक्तिगत रूप से सदस्यता लेता हूं, क्योंकि इसमें अलग-अलग जीवन चक्र हो सकते हैं।

जवाबों:


6

RxJS अतुल्यकालिक संचालन के प्रबंधन के लिए एक मूल्यवान संसाधन है और जहां संभव हो, आपके कोड (सदस्यता की संख्या को कम करने सहित) को सरल बनाने के लिए इसका उपयोग किया जाना चाहिए। समान रूप से, एक अवलोकन योग्य स्वचालित रूप से उस अवलोकन के लिए सदस्यता का पालन नहीं किया जाना चाहिए, अगर RxJS एक समाधान प्रदान करता है जो आपके आवेदन में सदस्यता की कुल संख्या को कम कर सकता है।

हालांकि, ऐसी परिस्थितियां हैं जहां सदस्यता बनाना फायदेमंद हो सकता है जो कड़ाई से 'आवश्यक' नहीं है:

एक उदाहरण अपवाद - एक ही टेम्पलेट में वेधशालाओं का पुन: उपयोग

अपने पहले उदाहरण को देखते हुए:

// Component:

this.value$ = this.store$.pipe(select(selectValue));

// Template:

<div>{{value$ | async}}</div>

यदि मूल्य $ केवल एक बार एक टेम्पलेट में उपयोग किया जाता है, तो मैं कोड अर्थव्यवस्था और स्वत: सदस्यता के लिए async पाइप और इसके लाभों का लाभ उठाऊंगा। हालाँकि इस उत्तर के अनुसार , एक टेम्पलेट में एक ही async चर के कई संदर्भों से बचा जाना चाहिए, जैसे:

// It works, but don't do this...

<ul *ngIf="value$ | async">
    <li *ngFor="let val of value$ | async">{{val}}</li>
</ul>

इस स्थिति में, मैं इसके बजाय एक अलग सदस्यता बनाऊंगा और अपने घटक में एक गैर-एसिंक्स चर को अपडेट करने के लिए इसका उपयोग करूंगा:

// Component

valueSub: Subscription;
value: number[];

ngOnInit() {
    this.valueSub = this.store$.pipe(select(selectValue)).subscribe(response => this.value = response);
}

ngOnDestroy() {
    this.valueSub.unsubscribe();
}

// Template

<ul *ngIf="value">
    <li *ngFor="let val of value">{{val}}</li>
</ul>

तकनीकी रूप से, इसके बिना एक ही परिणाम प्राप्त करना संभव है valueSub, लेकिन आवेदन की आवश्यकताओं का मतलब यह सही विकल्प है।

सदस्यता लेने का निर्णय लेने से पहले एक पर्यवेक्षक की भूमिका और जीवन को ध्यान में रखते हुए

यदि दो या अधिक वेधशालाएं केवल एक साथ लेने पर उपयोग की जाती हैं, तो उन्हें एक एकल सदस्यता में संयोजित करने के लिए उपयुक्त RxJS ऑपरेटरों का उपयोग किया जाना चाहिए।

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

जहां किसी भी व्यक्ति के पर्यवेक्षक स्वतंत्र रूप से उपयोगी होते हैं, वहां अलग-अलग सदस्यता (ओं) का लचीलापन और स्पष्टता पर विचार किया जा सकता है। लेकिन मेरे प्रारंभिक वक्तव्य के अनुसार, प्रत्येक पर्यवेक्षित के लिए एक सदस्यता स्वचालित रूप से नहीं बनाई जानी चाहिए, जब तक कि ऐसा करने का कोई स्पष्ट कारण न हो।

सदस्यता समाप्त करने के बारे में:

अतिरिक्त सदस्यता के खिलाफ एक बिंदु यह है कि अधिक सदस्यता रद्द करने की आवश्यकता है। जैसा कि आपने कहा है, हम यह मानेंगे कि सभी आवश्यक सदस्यता रद्द कर दी गई हैं, लेकिन वास्तविक जीवन हमेशा सुचारू रूप से नहीं चलता है! फिर, आरएक्सजेएस इस प्रक्रिया को कारगर बनाने के लिए उपयोगी उपकरण (जैसे पहले () ) प्रदान करता है, जो कोड को सरल बनाता है और मेमोरी डिस्क की क्षमता को कम करता है। यह लेख प्रासंगिक जानकारी और उदाहरण प्रदान करता है, जो मूल्य के हो सकते हैं।

व्यक्तिगत वरीयता / वाचालता बनाम मरोड़:

अपनी प्राथमिकताओं को ध्यान में रखें। मैं कोड वर्बोसिटी के बारे में एक सामान्य चर्चा की ओर नहीं जाना चाहता, लेकिन इसका उद्देश्य बहुत अधिक 'शोर' के बीच सही संतुलन का पता लगाना और अपने कोड को अत्यधिक गुप्त बनाना होना चाहिए। यह देखने लायक हो सकता है


पहले आपके विस्तृत जवाब के लिए धन्यवाद! # 1 के बारे में: मेरे दृष्टिकोण से एसिंक्श पाइप भी एक सदस्यता / साइड इफेक्ट है, बस यह एक निर्देश के अंदर मुखौटा है। # 2 के बारे में आप कृपया कुछ कोड नमूना जोड़ सकते हैं, मुझे वह बात नहीं मिलती जो आप मुझे बता रहे हैं। सदस्यता रद्द करने के बारे में: मेरे पास पहले कभी ऐसा नहीं था कि सदस्यता के लिए किसी भी अन्य स्थान पर सदस्यता समाप्त करने की आवश्यकता होती है। पहले () वास्तव में डिफ़ॉल्ट रूप से आपके लिए सदस्यता समाप्त करने का प्रबंधन नहीं करता है: 0 उत्सर्जन = सदस्यता खुला, हालांकि घटक नष्ट हो गया है।
जोनाथन स्टेलवाग

1
पॉइंट 2 वास्तव में सिर्फ प्रत्येक अवलोकन की भूमिका पर विचार करने के बारे में था, जब यह तय करना था कि सदस्यता का भी पालन करना है, बजाय किसी सदस्यता के साथ प्रत्येक अवलोकन योग्य का पालन करना। इस बिंदु पर, मैं आपको मध्यम . com / @ benlesh / rxjs-dont-unsubscribe-6753ed4fda87 पर देखने का सुझाव दूंगा , जो कहता है: "बहुत से सब्सक्रिप्शन ऑब्जेक्ट को अपने आस-पास रखना एक संकेत है जिसे आप अपनी सदस्यता को अनिवार्य रूप से प्रबंधित कर रहे हैं, और लाभ नहीं उठा रहे हैं Rx की शक्ति। "
मैट सॉन्डर्स

1
सराहा धन्यवाद @JonathanStellwag आरई कॉलबैक जानकारी के लिए भी धन्यवाद - आपके ऐप्स में, क्या आप इसे रोकने के लिए स्पष्ट रूप से हर सदस्यता (यहां तक ​​कि जहां पहले () का उपयोग किया जाता है) से सदस्यता समाप्त करते हैं?
मैट सॉन्डर्स

1
हां, है। वर्तमान परियोजना में हमने सभी नोड्स के लगभग 30% को हमेशा के लिए केवल अनसब्सक्राइब करके चारों ओर लटका दिया।
जोनाथन स्टेलवाग

2
सदस्यता समाप्त करने के लिए मेरी प्राथमिकता takeUntilएक फ़ंक्शन के साथ संयोजन में है जिसे कहा जाता है ngOnDestroy। यह एक लाइनर है जो इसे पाइप में जोड़ता है takeUntil(componentDestroyed(this)):। stackoverflow.com/a/60223749/5367916
कर्ट हैमिल्टन

2

यदि सदस्यता को अनुकूलित करना आपका एंडगेम है, तो तार्किक चरम पर क्यों न जाएं और बस इस सामान्य पैटर्न का पालन करें:

 const obs1$ = src1$.pipe(tap(effect1))
 const obs2$ = src2$pipe(tap(effect2))
 merge(obs1$, obs2$).subscribe()

विशेष रूप से टैप में साइड इफेक्ट्स को निष्पादित करना और मर्ज के साथ सक्रिय करने का मतलब है कि आपके पास केवल एक सदस्यता है।

ऐसा न करने का एक कारण यह है कि आप RxJS को उपयोगी बनाते हैं। जो कि अवलोकनीय धाराओं की रचना करने की क्षमता है, और आवश्यकतानुसार स्ट्रीम से सदस्यता / सदस्यता समाप्त कर सकते हैं।

मैं तर्क दूंगा कि आपकी वेधशालाएँ तार्किक रूप से बनाई जानी चाहिए, और सदस्यता को कम करने के नाम पर प्रदूषित या भ्रमित नहीं होना चाहिए। क्या फू प्रभाव तार्किक रूप से बार प्रभाव के साथ जोड़ा जाना चाहिए? क्या एक को दूसरे की आवश्यकता है? जब कभी http $ का उत्सर्जन होता है तो क्या मैं संभवतः ट्रिगर फू को नहीं चाहूंगा? क्या मैं असंबंधित कार्यों के बीच अनावश्यक युग्मन बना रहा हूं? ये सब एक धारा में डालने से बचने के कारण हैं।

यह सब एरर हैंडलिंग पर भी विचार नहीं कर रहा है जो कि कई सब्सक्रिप्शन IMO के साथ मैनेज करना आसान है


आपके उत्तर के लिए धन्यवाद। मुझे खेद है कि मैं केवल एक उत्तर को स्वीकार कर सकता हूं। आपका उत्तर वही है जो @Matt Saunders द्वारा लिखे गए के समान है। इसका सिर्फ एक और नजरिया है। मैट के प्रयास के कारण मैंने उसे स्वीकार कर लिया। मुझे आशा है कि आप मुझे माफ़ कर सकते हैं :)
जोनाथन स्टेलवाग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.