Max Liapkalo
Max Liapkalo

Reputation: 121

RxJs: Observable from array of promises

I am very new to RxJs and the problem I faced looks quite complicated for me. So, I have the following sample code

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

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

I have an array of 10 requests which I would like to process somehow(as an array of resolved Promise values) in my subscribe handler. The example above works just fine when I pass in only one request instead of array, but when it comes to the array I receive

TypeError: response.json is not a function

Upvotes: 3

Views: 1742

Answers (3)

Roberto Zvjerković
Roberto Zvjerković

Reputation: 10127

When from takes a promise as an argument it just converts it to an observable.

You can return an array of observables instead:

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

And then get their value by combining the streams, perhaps with forkJoin:

forkJoin(requests).subscribe(results => console.log(results));

Upvotes: 1

martin
martin

Reputation: 96891

You can use forkJoin. The important thing here is that in RxJS Promises are always turned into Observables that emit once and then complete. So you don't even need to make any conversion.

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

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

forkJoin is typically used with an array of Observables but it works with Promises as well with zero effort.

Live demo: https://stackblitz.com/edit/rxjs-gcorux

Upvotes: 2

cuddlemeister
cuddlemeister

Reputation: 1775

from accepts only 1 promise. You can solve it like this: from(Promise.all(requests))

And use map instead of switchMap. In switchmap you should return another observable, not a value.

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

And don't forget that processing an array of promises will return array of values, so you should not just get a response.json(), but do it for each element in the array

Upvotes: 1

Related Questions