Вызвать api для каждого элемента в Observable <sourceitem []> и «объединить» его с Observable <targetitem []> - PullRequest
0 голосов
/ 07 сентября 2018

У меня есть Observable с предметами, которые выбирает пользователь. Каждый выбранный элемент используется в качестве источника для вызова API. И результаты вызова API должны быть «объединены» с Observable.

То, что я не понимаю, это то, как я объединяю результаты обратно. Я попытался использовать оператор сканирования, но «аккумулятор» только «растет».

У меня есть это:

import {
  Observable,
  Subject,
  of ,
  from
} from 'rxjs';
import {
  map,
  merge,
  flatMap
} from 'rxjs/operators';

function apiUri(albumId: String) {
  return `https://jsonplaceholder.typicode.com/albums/${albumId}`
}


const albums$ = new Subject < String[] > ();

const responseStream = albums$.pipe(
  flatMap(albumIds => albumIds),
  flatMap(id => from(fetch(apiUri(id)))),
  flatMap(resp => resp.json()),
  /* I'm in the dark on how to "merge" it back into an Observable<String[]> */
);

responseStream.subscribe(resp => console.log(resp))
const randomCodes1 = ['5', '1', '3'];
albums$.next(randomCodes1);

Ссылка Stackblitz с работающим примером: https://stackblitz.com/edit/rxjs-flatmap-galore?&file=index.ts

1 Ответ

0 голосов
/ 07 сентября 2018

Это код, который должен позволить вам создать responseStream, который вы ищете.

const responseStream = albums$.pipe(
  map(albumIds => albumIds.map(id => from(fetch(apiUrl(id))).pipe(mergeMap(resp => resp.json())))),
  mergeMap(obsOfIds => forkJoin(obsOfIds)),
);

Прежде всего, давайте сосредоточимся на forkJoin. Вы можете передать этому оператору массив Observables, и этот оператор вернет Observable, который испускается, когда все Observables во входном массиве испустили, и он выпустит массив со значениями, испускаемыми каждым Observable во входном массиве.

Это то, что вы, вероятно, ищете. Как создать массив Observables, который вам нужен? Это то, что выполняет первый оператор map.

Рассмотрим одну вещь, когда смотришь на этого оператора.

map(albumIds => albumIds.map(id => from(fetch(apiUrl(id))).pipe(mergeMap(resp => resp.json()))))

Вы используете 2 раза map, но это НЕ одно и то же map. Первый map, то есть самый внешний, является оператором map Observable. Вторым map, то есть самым внутренним, является map метод массива.

Я обновил ваш стек, и похоже, он работает правильно.

...