clse
clse

Reputation: 764

rxjs sequential dynamic number of api calls

Trying to create an rxjs pipeline that will do the following: Essentially I have an array of a dynamic number of API calls. Every time I need to make a new API call, I push it to the array.

Then, I transform the array into an array of RXJS switchmap operators. (The sequence of the calls doesn't matter, just that I need to make one call after the previous call finishes, and not at the same time).

Finally, I try to spread the array of rxjs operators inside a pipe:

const obsArray = [randomQuote(), getCatFacts(4), recipeSearch('oil')]
const OperatorWrap = obsArray.map((obs) => {
  return rxops.switchMap((val) => { return obs })
})



const pipeline= of(1).pipe(...OperatorWrap);

But I get a strange error message: enter image description here

Upvotes: 0

Views: 1322

Answers (2)

Mrk Sef
Mrk Sef

Reputation: 8062

merge: run the array of observables in parallel, emit results one at a time as they arrive:

We'll log the results to the console.

const obsArray = [randomQuote(), getCatFacts(4), recipeSearch('oil')];
merge(...obsArray).subscribe(console.log);

forkJoin: run the array of observables in parallel, emit results as an array

The array is actually the final value emitted by each observable. This means they must all emit > 0 values and must all complete. Often used for HTTP GET requests.

const obsArray = [randomQuote(), getCatFacts(4), recipeSearch('oil')];
forkJoin(obsArray).subscribe(console.log);

concat: Run the array of observables in order

Wait for obsArray[0] to complete before starting obsArray[1] and so on...

const obsArray = [randomQuote(), getCatFacts(4), recipeSearch('oil')];
concat(...obsArray).subscribe(console.log);

Array of operators

This should work pretty much like concat, though the situations where it's really recommended/required are slim and far between. Use concat instead.

The way pipe is implemented is meant to give typescript a way to check that the types match up throughout your functional composition. The downside is that it doesn't seem to behave well with the spread operator. I'm pretty sure it's safe to ignore this TS error.

GitHub: .pipe fn type overloads no longer support using spread arguments #3989

const obsArray = [randomQuote(), getCatFacts(4), recipeSearch('oil')];
const operatorFunctions = obsArray.map(obs => rxops.switchMap(_ => obs));

const pipeline = of(1).pipe(
  // @ts-ignore
  ...operatorFunctions
);

Upvotes: 0

shutsman
shutsman

Reputation: 2510

concatAll it is what do you need

concatAll - Collect observables and subscribe to next when previous completes.

I did an example: https://stackblitz.com/edit/angular7-rxjs-jy2gda?file=src/app/app.component.ts

    const APIs = [
      `https://jsonplaceholder.typicode.com/todos/1`,
      `https://jsonplaceholder.typicode.com/todos/2`,
      `https://jsonplaceholder.typicode.com/todos/3`,
      `https://jsonplaceholder.typicode.com/todos/4`
    ].map(url => this.http.get(url));
    from(APIs)
      .pipe(concatAll())
      .subscribe();

enter image description here

Upvotes: 1

Related Questions