Zaczynam używać RxJS i nie rozumiem, dlaczego w tym przykładzie musimy użyć funkcji takiej jak flatMap
lub concatAll
; gdzie jest tablica tablic?
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)})
Jeśli ktoś może wizualnie wyjaśnić, co się dzieje, będzie to bardzo pomocne.
javascript
rxjs
user233232
źródło
źródło
flatMap
został nazwanymapThenFlatten
, byłoby mniej zagmatwane.Odpowiedzi:
Kiedy zacząłem się przyglądać,
Rxjs
natknąłem się też na ten kamień. Pomogło mi to:flatMap
: http://reactivex.io/documentation/operators/flatmap.htmlflatMap
tam, musiszmergeMap
zamiast tego zajrzeć (inna nazwa).wreszcie patrząc na informacje o typie z RxJava. Brak wpisywania kodu JavaScript nie pomoże tutaj. Zasadniczo, jeśli
Observable<T>
oznacza obserwowalny obiekt, który wypycha wartości typu T, toflatMap
przyjmuje funkcję typuT' -> Observable<T>
jako argument i zwracaObservable<T>
.map
przyjmuje funkcję typuT' -> T
i zwracaObservable<T>
.Wracając do twojego przykładu, masz funkcję, która generuje obietnice z ciągu adresu URL. Więc
T' : string
iT : promise
. Z tego, co powiedzieliśmy wcześniejpromise : Observable<T''>
, więcT : Observable<T''>
zT'' : html
. Jeśli umieścisz tę obietnicę produkującą funkcjęmap
, otrzymaszObservable<Observable<T''>>
to, czego chceszObservable<T''>
: chcesz, aby obserwowalne emitowałyhtml
wartości.flatMap
nazywa się tak, ponieważ spłaszcza (usuwa obserwowalną warstwę) wynik zmap
. W zależności od Twojego doświadczenia może to być dla Ciebie język chiński, ale wszystko stało się dla mnie jasne dzięki wpisywaniu informacji i rysowaniu stąd: http://reactivex.io/documentation/operators/flatmap.html .źródło
return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl));
doreturn jQuery.getJSON(requestUrl);
jakflatMap
przyjmuje również funkcję selektora która zwraca obietnica czyli funkcję typuT' -> Promise
.T’ -> T
? RozumiemT
jako rodzaj, ale co to jest apostrof i nietłusta strzała?['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]]
Używasz flatMap, gdy masz Observable, którego wyniki są bardziej Observables.
Jeśli masz obserwowalne, które są produkowane przez inne obserwowalne, nie możesz ich filtrować, redukować ani mapować bezpośrednio, ponieważ masz Observable, a nie dane. Jeśli utworzysz obserwowalne, wybierz flatMap over map; to wszystko w porządku.
Podobnie jak w drugim fragmencie, jeśli wykonujesz operację asynchroniczną, musisz użyć flatMap.
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>
źródło
Ludzie mają tendencję do nadmiernego komplikowania rzeczy , podając definicję, która mówi:
Przysięgam, że ta definicja wciąż mnie dezorientuje, ale wyjaśnię to w najprostszy sposób, czyli na przykładzie
Nasza sytuacja : mamy obserwowalną, która zwraca dane (prosty adres URL), których zamierzamy użyć do wykonania wywołania HTTP, które zwróci obserwowalne zawierające potrzebne nam dane, abyś mógł zwizualizować sytuację w następujący sposób:
Observable 1 |_ Make Http Call Using Observable 1 Data (returns Observable_2) |_ The Data We Need
więc jak widać, nie możemy bezpośrednio dotrzeć do potrzebnych nam danych, więc pierwszym sposobem na odzyskanie danych możemy użyć zwykłych subskrypcji, takich jak ta:
Observable_1.subscribe((URL) => { Http.get(URL).subscribe((Data_We_Need) => { console.log(Data_We_Need); }); });
to działa, ale jak widać, musimy zagnieżdżać subskrypcje, aby uzyskać nasze dane, obecnie nie wygląda to źle, ale wyobraź sobie, że mamy 10 zagnieżdżonych subskrypcji, które stałyby się nie do utrzymania.
więc lepszym sposobem rozwiązania tego problemu jest użycie operatora,
flatMap
który zrobi to samo, ale pozwoli nam uniknąć tej zagnieżdżonej subskrypcji:Observable_1 .flatMap(URL => Http.get(URL)) .subscribe(Data_We_Need => console.log(Data_We_Need));
źródło
flatMap
przekształcić elementy emitowane przez Observable w nowe Observable, a następnie spłaszcza emisje z tych do jednego Observable.Sprawdź poniższy scenariusz, w którym
get("posts")
zwraca Observable, który jest „spłaszczany” przezflatMap
.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.
źródło
Prosty:
[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]]
źródło
To nie jest tablica tablic. To jest obserwowalne z obserwowalnymi.
Poniższe zwraca obserwowalny strumień ciągu.
requestStream .map(function(requestUrl) { return requestUrl; });
Chociaż zwraca to obserwowalny strumień obserwowalnego strumienia json
requestStream .map(function(requestUrl) { return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl)); });
flatMap
automatycznie spłaszcza obserwowalne dla nas, dzięki czemu możemy bezpośrednio obserwować strumień jsonźródło
flatMap
(imap
) nie są specjalne dla tablic. Możliwe jest zdefiniowanie tych operacji na dowolnym ogólnym pojemniku lub opakowaniu, w tym na tablicach, słownikach, „opcjach”, strumieniach reaktywnych, obietnicach, wskaźnikach, a nawet samych funkcjach. Jest to wyłaniająca się właściwość konstrukcji matematycznej zwanej monadą. Wszystkie powyższe przykłady spełniają wymagania bycia monadą, więc wszystkim można nadać definicjęmap
i aflatMap
(z pewnymi zastrzeżeniami).Tutaj, aby pokazać równoważną implementację flatMap przy użyciu subskrybentów.
Bez flatMap:
this.searchField.valueChanges.debounceTime(400) .subscribe( term => this.searchService.search(term) .subscribe( results => { console.log(results); this.result = results; } ); );
Z flatMapą:
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
Mam nadzieję, że to pomoże.
Olivier.
źródło
Observable to obiekt, który emituje strumień zdarzeń: Next, Error i Completed.
Gdy funkcja zwraca Observable, nie zwraca strumienia, ale instancję Observable.
flatMap
Operator po prostu odwzorowuje to wystąpienie do strumienia.To jest zachowanie w
flatMap
porównaniu zmap
: Wykonaj daną funkcję i spłaszcz wynikowy obiekt w strumień.źródło
Z flatMap
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)})
Bez flatMap
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)}) })
źródło
Nie jestem głupi, ale musiałem to przeczytać 10 razy i nadal nie rozumiem. Kiedy czytam fragment kodu:
[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]
wtedy mógłbym zrozumieć, co się dzieje, robi dwie rzeczy:
*) Słowo transformacji mówi, że element można przekształcić w coś innego.
Następnie operator scalania staje się jasny, wykonuje spłaszczanie bez mapowania. Dlaczego nie nazwać go mergeMap ? Wygląda na to, że istnieje również alias mergeMap o tej nazwie dla flatMap .
źródło