Зачем нам нужно использовать 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)})

Если кто-то может визуально объяснить, что происходит, это будет очень полезно.

Ответ 1

Когда я начал смотреть на Rxjs, я тоже наткнулся на этот камень. Мне помогло следующее:

  • документация от reactivex.io. Например, для flatMap: http://reactivex.io/documentation/operators/flatmap.html
  • документация из rxmarbles: http://rxmarbles.com/. Вы не найдете там flatMap, вместо этого вы должны посмотреть switchMap (другое имя).
  • введение в Rx, которое вам не хватало: https://gist.github.com/staltz/868e7e9bc2a7b8c1f754. Он рассматривает очень похожий пример. В частности, речь идет о том, что обещание сродни наблюдаемому испусканию только одного значения.
  • наконец, посмотрев информацию о типе из RxJava. Javascript, который не набирается, не помогает здесь. В принципе, если Observable<T> обозначает наблюдаемый объект, который толкает значения типа T, то flatMap принимает в качестве аргумента функцию типа T' -> Observable<T> и возвращает Observable<T>. map выполняет функцию типа T' -> T и возвращает Observable<T>.

    Возвращаясь к вашему примеру, у вас есть функция, которая создает promises из строки 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

['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, если у вас есть Observable, результаты которого больше Observables.

Если у вас есть наблюдаемое, которое создается другим наблюдаемым, вы не можете фильтровать, уменьшать или сопоставлять его напрямую, потому что у вас есть Наблюдаемый, а не данные. Если вы создаете наблюдаемый, выберите flatMap over map; тогда вы в порядке.

Как и во втором фрагменте, если вы выполняете операцию async, вам нужно использовать 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>

Ответ 3

Это не массив массивов. Это наблюдаемое наблюдение (ы).

Следующее возвращает наблюдаемый поток строки.

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

Пока это возвращает наблюдаемый поток наблюдаемого потока json

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

flatMap выравнивает наблюдаемое автоматически для нас, поэтому мы можем непосредственно наблюдать поток json

Ответ 4

Простой:

[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]]

Ответ 5

flatMap преобразует элементы, испускаемые наблюдаемым в новые наблюдаемые, затем выравнивает выбросы от них в единый наблюдаемый.

Посмотрите нижеприведенный сценарий, где get("posts") возвращает Observable, "сплющенный" на 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.

Ответ 6

Наблюдаемый - это объект, который испускает поток событий: Далее, Ошибка и Выполнено.

Когда ваша функция возвращает Observable, она не возвращает поток, а экземпляр Observable. Оператор flatMap просто отображает этот экземпляр в поток.

Это поведение flatMap по сравнению с map: выполнить заданную функцию и сгладить результирующий объект в поток.

Ответ 7

С 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)})
})

Ответ 8

Люди склонны усложнять вещи, давая определение, в котором говорится:

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));