Rx Js: наблюдаемый из массива обещаний - PullRequest
2 голосов
/ 19 января 2020

Я очень плохо знаком с Rx Js, и проблема, с которой я столкнулся, выглядит довольно сложной для меня. Итак, у меня есть следующий пример кода

const requests = [...Array(10)].map((_, i) => fetch(`${ ENDPOINT }/${ ++i }`));

from(requests).pipe(
  switchMap(response => response.json()),
  catchError(val => of(val))
).subscribe(value => { ... })

У меня есть массив из 10 запросов, которые я хотел бы как-то обработать (как массив разрешенных значений Promise) в моем обработчике подписки. Приведенный выше пример прекрасно работает, когда я передаю только один запрос вместо массива, но когда дело доходит до массива, я получаю

TypeError: response. json не является функцией

Ответы [ 3 ]

1 голос
/ 19 января 2020

Вы можете использовать forkJoin. Здесь важно то, что в Rx JS Обещания всегда превращаются в Observables, которые излучают один раз, а затем завершают. Таким образом, вам даже не нужно выполнять какие-либо преобразования.

const requests = [
  Promise.resolve(1),
  Promise.resolve(2),
  Promise.resolve(3),
];

forkJoin(requests).subscribe(console.log);

forkJoin обычно используется с массивом Observables, но он также работает с Promises без усилий.

Live демо: https://stackblitz.com/edit/rxjs-gcorux

1 голос
/ 20 января 2020

Когда from принимает обещание в качестве аргумента, оно просто преобразует его в наблюдаемую.

Вместо этого вы можете вернуть массив наблюдаемых:

const requests = [...Array(10)].map((_, i) => from(fetch(`${ENDPOINT}/${++i}`)));

И затем получить их значение путем объединения потоков, возможно, с forkJoin:

forkJoin(requests).subscribe(results => console.log(results));
1 голос
/ 19 января 2020

from принимает только 1 обещание. Вы можете решить это следующим образом: from(Promise.all(requests))

И использовать map вместо switchMap. В switchmap вы должны возвращать другое наблюдаемое, а не значение.

from(Promise.all(requests)).pipe(
  map(responses => responses.map(response => response.json())),
  catchError(val => of(val))
).subscribe(value => { ... })

И не забывайте, что обработка массива обещаний вернет массив значений, поэтому вы не должны просто получить ответ. json (), но сделать это для каждого элемента в массиве

...