Почему мы должны использовать flatMap?
Я начинаю использовать 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)})
Если кто-то может наглядно объяснить, что происходит, это будет очень полезно.
9 ответов:
когда я начал смотреть на
Rxjs
Я тоже наткнулся на этот камень. Мне помогло следующее:
- документация от reactivex.io . Например, для
flatMap
: http://reactivex.io/documentation/operators/flatmap.html- документация от rxmarbles:http://rxmarbles.com/. вы не найдете
flatMap
нет, вы должны посмотретьmergeMap
вместо этого (другое имя).- введение в Rx что вы пропали без вести:https://gist.github.com/staltz/868e7e9bc2a7b8c1f754. он обращается к очень похожему примеру. В частности, он обращается к тому факту, что обещание сродни наблюдаемому излучению только одного значения.
наконец, глядя на информацию о типе из RxJava. Javascript не набирается здесь не помогает. В принципе, если
Observable<T>
обозначает наблюдаемый объект, который толкает значения типа 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
.
['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]]
вы используете flatMap, когда у вас есть наблюдаемый, результаты которого более заметны.
если у вас есть наблюдаемое, которое создается другим наблюдаемым, вы не можете фильтровать, уменьшать или сопоставлять его напрямую, потому что у вас есть наблюдаемые не данные. Если вы создаете наблюдаемый выбор flatMap над картой; тогда вы в порядке.
как и во втором фрагменте, если вы делаете асинхронную операцию, которую вам нужно использовать 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>
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.
Это не массив массивов. Это наблюдаемое из наблюдаемых(ов).
следующее возвращает наблюдаемый поток строки.
requestStream .map(function(requestUrl) { return requestUrl; });
В то время как это возвращает наблюдаемый поток наблюдаемого потока json
requestStream .map(function(requestUrl) { return Rx.Observable.fromPromise(jQuery.getJSON(requestUrl)); });
flatMap
сглаживает наблюдаемое автоматически для нас, чтобы мы могли наблюдать поток json напрямую
наблюдаемый-это объект, который испускает поток событий: Next, Error и Completed.
когда ваша функция возвращает Observable, она возвращает не поток, а экземпляр Observable. Элемент
flatMap
оператор просто сопоставляет этот экземпляр потоку.это поведение
flatMap
по сравнению сmap
: выполните данную функцию и сгладьте полученный объект в поток.
просто:
[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]]
люди склонны усложнять вещи дать определение, которое говорит:
flatMap преобразует элементы, излучаемые наблюдаемым в Наблюдаемые, затем сглаживают выбросы от них в один Наблюдаемый
клянусь, это определение все еще смущает меня, но я собираюсь объяснить его самым простым способом, который заключается в использовании примера
В Нашей Ситуации: у нас есть наблюдаемый, который возвращает данные (простой 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));
С 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)})
без 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)}) })
здесь, чтобы показать эквивалентную реализацию flatMap с помощью подписывается.
без flatMap:
this.searchField.valueChanges.debounceTime(400) .subscribe( term => this.searchService.search(term) .subscribe( results => { console.log(results); this.result = results; } ); );
С 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
надеюсь, что это может помочь.
Оливье.