हमें फ्लैटपाइप का उपयोग करने की आवश्यकता क्यों है?


92

मैं RxJS का उपयोग करना शुरू कर रहा हूं और मुझे समझ में नहीं आ रहा है कि इस उदाहरण में हमें किसी फ़ंक्शन का उपयोग करने की आवश्यकता है flatMapया concatAll; यहाँ ऐरे की सरणी कहाँ है?

var requestStream = Rx.Observable.just('https://api.github.com/users');

var responseMetastream = requestStream
  .flatMap(function(requestUrl) {
    return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
  });

responseMetastream.subscribe(url => {console.log(url)})

यदि कोई नेत्रहीन बता सकता है कि क्या हो रहा है, तो यह बहुत मददगार होगा।


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

5
मुझे लगता है कि अगर flatMapनाम रखा गया होता mapThenFlatten, तो यह कम भ्रमित करने वाला होता।
बकरी

जवाबों:


73

जब मेरी नज़र Rxjsउस पर पड़ी तो मैंने भी उस पत्थर पर ठोकर मारी। निम्नलिखित में से मुझे क्या मदद मिली:

  • reactivex.io से प्रलेखन। उदाहरण के लिए, इसके लिए flatMap: http://reactivex.io/documentation/operators/flatmap.html
  • rxmarbles से प्रलेखन: http://rxmarbles.com/ । आपको flatMapवहां नहीं मिलेगा , आपको mergeMapइसके बजाय (किसी अन्य नाम) को देखना होगा ।
  • आरएक्स का परिचय जो आपको याद आ रहा है: https://gist.github.com/staltz/868e7e9bc2a7b8c1f754 । यह एक बहुत ही समान उदाहरण को संबोधित करता है। विशेष रूप से यह इस तथ्य को संबोधित करता है कि एक वादा केवल एक मूल्य का पालन करने योग्य अवलोकन के समान है।
  • अंत में RxJava से टाइप जानकारी देख रहे हैं। जावास्क्रिप्ट टाइप नहीं होने से यहाँ मदद नहीं मिलती है। मूल रूप से यदि Observable<T>एक अवलोकनीय वस्तु को दर्शाता है जो टाइप टी के मूल्यों को आगे बढ़ाता है, तो इसके तर्क के रूप flatMapमें प्रकार का एक फ़ंक्शन लेता है T' -> Observable<T>, और वापस लौटता है Observable<T>mapप्रकार T' -> Tऔर रिटर्न देता है Observable<T>

    अपने उदाहरण पर वापस जा रहे हैं, आपके पास एक फ़ंक्शन है जो एक url स्ट्रिंग से वादे पैदा करता है। तो T' : string, और T : promise। और जो हमने पहले कहा promise : Observable<T''>, उससे T : Observable<T''>, साथ T'' : html। यदि आप उस वादे के फलन समारोह में डालते हैं map, तो आपको वह मिलता है Observable<Observable<T''>>जब आप चाहते हैं Observable<T''>: आप चाहते हैं कि htmlमानों का पालन करने योग्य हो । flatMapइस तरह कहा जाता है क्योंकि यह समतल करता है (एक अवलोकनीय परत को हटाता है) से परिणाम map। आपकी पृष्ठभूमि के आधार पर, यह आपके लिए चीनी हो सकता है, लेकिन जानकारी टाइप करने और यहां से आरेखण के साथ सब कुछ मेरे लिए स्पष्ट हो गया है: http://reactivex.io/documentation/operators/flatmap.html


2
मुझे लगता है कि आप को आसान बनाने के लिए सक्षम होना चाहिए उल्लेख करना भूल गया return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));के return jQuery.getJSON(requestUrl);रूप में flatMapभी एक चयनकर्ता समारोह किस प्रकार के वादे यानी फ़ंक्शन को स्वीकार करता है T' -> Promise
user3743222

2
वाह, वह GitHub Gist ( gist.github.com/staltz/868e7e9bc2a7b8c1f754 ) शानदार है। मैं इसे RxJS जैसे किसी भी ReactiveX लाइब्रेरी के साथ काम करने की सलाह देता हूं।
जैकब स्टैम

@ जैकोब्स्टाम मैं सहमत हूँ। बस चीजें आसान हो जाती हैं।
क्रुएलजाइन

इस वाक्यविन्यास का क्या अर्थ है T’ -> T:? मैं Tएक सामान्य के रूप में समझता हूं , लेकिन एपोस्ट्रोफ और वसा-बाण क्या है?
१२५२ 13४48

आप उत्तर में कहीं भी अर्थ बदले बिना X या Y द्वारा T 'को बदल सकते हैं। तीर प्रकार के हस्ताक्षर के लिए हास्केल संकेतन है। तो T '-> T एक फ़ंक्शन के लिए हस्ताक्षर है जो टाइप T का एक तत्व लेता है और टाइप T का एक तत्व देता है
user3743222

124
['a','b','c'].flatMap(function(e) {
    return [e, e+ 'x', e+ 'y',  e+ 'z'  ];
});
//['a', 'ax', 'ay', 'az', 'b', 'bx', 'by', 'bz', 'c', 'cx', 'cy', 'cz']


['a','b','c'].map(function(e) {
    return [e, e+ 'x', e+ 'y',  e+ 'z'  ];
});
//[Array[4], Array[4], Array[4]]

जब आप एक ऑब्जर्वेबल होते हैं तो आप फ्लैटपाइप का उपयोग करते हैं जिसके परिणाम अधिक ऑब्जर्वेबल होते हैं।

यदि आपके पास एक ऑब्जर्वेबल है, जो एक अन्य ऑब्जर्वेबल द्वारा निर्मित है, तो आप इसे फ़िल्टर नहीं कर सकते, कम कर सकते हैं, या सीधे मैप कर सकते हैं क्योंकि आपके पास ऑब्जर्वेबल है डेटा नहीं। यदि आप नक्शे पर एक अवलोकन विकल्प का चयन करते हैं; तब आप ठीक हैं।

दूसरे स्निपेट की तरह, यदि आप एसिंक्स ऑपरेशन कर रहे हैं तो आपको फ्लैटपाइप का उपयोग करने की आवश्यकता है।

var source = Rx.Observable.interval(100).take(10).map(function(num){
    return num+1
});
source.subscribe(function(e){
    console.log(e)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.1/Rx.min.js"></script>

var source = Rx.Observable.interval(100).take(10).flatMap(function(num){
    return Rx.Observable.timer(100).map(() => num)
});
source.subscribe(function(e){
    console.log(e)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.1/Rx.min.js"></script>


31

flatMap एक वेधशाला द्वारा उत्सर्जित वस्तुओं को नए वेधशालाओं में बदलना, फिर उनमें से उत्सर्जन को एक ही वेधशाला में बदलना।

नीचे के परिदृश्य को देखें जहां get("posts")एक अवलोकन योग्य है जो "चपटा" है flatMap

myObservable.map(e => get("posts")).subscribe(o => console.log(o));
// this would log Observable objects to console.  

myObservable.flatMap(e => get("posts")).subscribe(o => console.log(o));
// this would log posts to console.

2
अच्छा, सरल उत्तर। मुझे लगता है कि यह सबसे अच्छा हो सकता है।
विघ्न

"फ़्लैटबॉल एक ऑब्जर्वेबल द्वारा उत्सर्जित वस्तुओं को नए वेधशालाओं में बदल देता है, फिर उन लोगों के उत्सर्जन को एक ऑब्जर्वेबल में बदल देता है।" यह उत्कृष्ट सामान है।
एमबीक

31

लोग जो कहते हैं परिभाषा देकर जटिल चीजों पर काबू पाते हैं:

फ़्लैटबॉल वेधशाला द्वारा उत्सर्जित वस्तुओं को वेधशालाओं में परिवर्तित करते हैं, फिर उनमे से उत्सर्जन को एक ही अवलोकन में समतल करते हैं

मैं कसम खाता हूं कि यह परिभाषा अभी भी मुझे भ्रमित करती है लेकिन मैं इसे सबसे सरल तरीके से समझाने जा रहा हूं जो एक उदाहरण का उपयोग करके है

हमारी स्थिति : हमारे पास एक अवलोकन योग्य है जो डेटा (सरल URL) लौटाता है जिसे हम एक HTTP कॉल करने के लिए उपयोग करने जा रहे हैं जो एक अवलोकन योग्य डेटा को लौटाएगा जिसकी हमें आवश्यकता है ताकि आप इस तरह की स्थिति की कल्पना कर सकें:

Observable 1
    |_
       Make Http Call Using Observable 1 Data (returns Observable_2)
            |_
               The Data We Need

इसलिए जैसा कि आप देख सकते हैं कि हम उस डेटा तक नहीं पहुँच सकते हैं जिसकी हमें सीधे ज़रूरत है इसलिए डेटा को पुनः प्राप्त करने का पहला तरीका जो हम सामान्य सदस्यताएँ जैसे उपयोग कर सकते हैं:

Observable_1.subscribe((URL) => {
         Http.get(URL).subscribe((Data_We_Need) => {
                  console.log(Data_We_Need);
          });
});

यह काम करता है लेकिन जैसा कि आप देख सकते हैं कि हमें अपना डेटा प्राप्त करने के लिए घोंसले की सदस्यता लेनी होगी यह वर्तमान में बुरा नहीं लगता है लेकिन कल्पना करें कि हमारे पास 10 नेस्टेड सदस्यता हैं जो कि अप्राप्य हो जाएंगे।

तो इसे संभालने का एक बेहतर तरीका यह है कि आप ऑपरेटर का उपयोग करें flatMapजो कि वही काम करेगा लेकिन हमें उस नेस्टेड सब्सक्रिप्शन से बचना चाहिए:

Observable_1
    .flatMap(URL => Http.get(URL))
    .subscribe(Data_We_Need => console.log(Data_We_Need));

19

सरल:

[1,2,3].map(x => [x, x * 10])
// [[1, 10], [2, 20], [3, 30]]

[1,2,3].flatMap(x => [x, x * 10])
// [1, 10, 2, 20, 3, 30]]

16

यह सरणियों की एक सरणी नहीं है। यह अवलोकनीय है।

निम्नलिखित स्ट्रिंग का एक अवलोकन योग्य स्ट्रीम देता है।

requestStream
  .map(function(requestUrl) {
    return requestUrl;
  });

जबकि यह जस्सन के अवलोकन योग्य धारा का एक अवलोकन योग्य प्रवाह देता है

requestStream
  .map(function(requestUrl) {
    return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
  });

flatMap हमारे लिए अवलोकनीय स्वचालित रूप से समतल करता है ताकि हम सीधे जस्सन धारा का निरीक्षण कर सकें


3
इस अवधारणा को समझना मुश्किल है, क्या आप कृपया टिप्पणियों को विज़ुअल में जोड़ सकते हैं, जिसका मतलब है कि "आप" ज्यूसन की एक नमूदार धारा को लौटाते हैं। धन्यवाद।
user233232

@ user233232, जैसे [x, x, x, x] को [[xxx], [[xxx], [xxx]]]
सेरकन

पहले वाक्य को समझने की कुंजी यह समझ रही है कि flatMap(और map) सरणियों के लिए विशेष नहीं हैं। किसी भी सामान्य कंटेनर या आवरण पर इन कार्यों को परिभाषित करना संभव है, जिसमें सरणियां, शब्दकोश, "वैकल्पिक", प्रतिक्रियाशील धाराएं, वादे, संकेत और यहां तक ​​कि स्वयं कार्य भी शामिल हैं। यह एक गणितीय निर्माण की एक आकस्मिक संपत्ति है जिसे मोनाड कहा जाता है। मिलने से ऊपर सभी उदाहरण एक इकाई होने के लिए आवश्यकताओं, और वे इसलिए सभी की एक परिभाषा दी जा सकती है mapऔर एक flatMap(कुछ कैविएट्स के साथ)।
mklbtz

14

यहां सब्सक्राइबर्स का उपयोग कर एक फ्लैटपाइप के बराबर कार्यान्वयन दिखाने के लिए।

बिना फ्लैटपोट के:

this.searchField.valueChanges.debounceTime(400)
.subscribe(
  term => this.searchService.search(term)
  .subscribe( results => {
      console.log(results);  
      this.result = results;
    }
  );
);

फ्लैटपाइप के साथ:

this.searchField.valueChanges.debounceTime(400)
    .flatMap(term => this.searchService.search(term))
    .subscribe(results => {
      console.log(results);
      this.result = results;
    });

http://plnkr.co/edit/BHGmEcdS5eQGX703eRRE?p=preview

आशा है कि यह मदद कर सकता है।

ओलिवर।


13

एक अवलोकन योग्य एक वस्तु है जो घटनाओं की एक धारा का उत्सर्जन करती है: अगला, त्रुटि और पूर्ण।

जब आपका फ़ंक्शन एक ऑब्जर्वेबल लौटाता है, तो यह एक स्ट्रीम नहीं लौट रहा है, लेकिन ऑब्जर्वेबल का एक उदाहरण है। flatMapऑपरेटर बस एक धारा है कि उदाहरण के नक्शे।

इसकी flatMapतुलना में यह व्यवहार है map: दिए गए कार्य को निष्पादित करें और परिणामी वस्तु को एक धारा में समतल करें।


7

फ्लैटपोट के साथ

var requestStream = Rx.Observable.just('https://api.github.com/users');

var responseMetastream = requestStream
  .flatMap(function(requestUrl) {
    return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
  });

responseMetastream.subscribe(json => {console.log(json)})

बिना फ्लैटपोट के

var requestStream = Rx.Observable.just('https://api.github.com/users');

var responseMetastream = requestStream
  .map(function(requestUrl) {
    return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
  });

responseMetastream.subscribe(jsonStream => {
  jsonStream.subscribe(json => {console.log(json)})
})

0

फ़्लैटबॉल वेधशाला द्वारा उत्सर्जित वस्तुओं को वेधशालाओं में परिवर्तित करते हैं, फिर उनमे से उत्सर्जन को एक ही अवलोकन में समतल करते हैं

मैं बेवकूफ नहीं हूं लेकिन मुझे 10 बार पढ़ना पड़ा और अभी भी नहीं मिला। जब मैंने कोड स्निपेट पढ़ा:

[1,2,3].map(x => [x, x * 10])
// [[1, 10], [2, 20], [3, 30]]

[1,2,3].flatMap(x => [x, x * 10])
// [1, 10, 2, 20, 3, 30]

तब मैं समझ सका कि क्या हो रहा है, यह दो काम करता है:

फ्लैटपाइप :

  1. नक्शा : परिवर्तन *) वेधशालाओं में उत्सर्जित आइटम।
  2. फ्लैट : फिर एक वेधशाला के रूप में उन वेधशालाओं को मर्ज करें।

*) ट्रांसफॉर्म शब्द कहता है कि आइटम को किसी और चीज में बदला जा सकता है।

फिर मर्ज ऑपरेटर के लिए स्पष्ट हो जाता है, यह मैपिंग के बिना सपाट करता है। इसे मर्ज मैप क्यों नहीं कहा जा रहा है ? ऐसा लगता है भी है एक उर्फ mergeMap के लिए है कि नाम के साथ flatMap

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