Home > OS >  How to use switchMap to subscribe only to the last, while using a concurrent parameter (only availab
How to use switchMap to subscribe only to the last, while using a concurrent parameter (only availab

Time:10-20

I have this code:

https://stackblitz.com/edit/so-74114000-n5t8dl?devtoolsheight=100&file=index.ts:L30

import './style.css';
import { of, from, mergeMap, delay, tap, defer, Observable, map, switchMap, combineLatest, } from 'rxjs';

GetIds()
  .pipe(mergeMap((x) => x.map((i) => fakeRequest(`#${i}`))))
  .pipe(mergeMap((req$) => req$, 3))
  .subscribe(
    (result) => console.log(`${result} DONE!`),
    (error) => console.error(error)
  );

function fakeRequest(label: string): Observable<string> {
  return defer(() =>
    of(label).pipe(
      tap(() => console.log(`> Fetching ${label}`)),
      delay(Math.random() * 5000   1250)
    )
  );
}

function GetIds(): Observable<number[]> {
  return of([1, 2, 3, 4, 5]).pipe(tap((qi) => console.log(`> id ${qi}`)));
}

It's faking a couple web requests with a max of 3 concurrent using mergeMap.

Output:

> id 1,2,3,4,5
> Fetching #1
> Fetching #2
> Fetching #3
#2 DONE!
> Fetching #4
#1 DONE!
> Fetching #5
#4 DONE!
#5 DONE!
#3 DONE!

I am missing one thing: I would like the "DONE" message to appear only at the end, once all the request are done. Currently the "DONE" message is appearing after each request.

CodePudding user response:

Instead of emitting each result as they are received, you can emit an array of all results once the source completes using toArray:

GetIds().pipe(
  mergeMap(x => getUpdateRequests(x)),
  mergeMap(req$ => req$, 3),
  toArray()
).subscribe(
  result => console.log(`${result} DONE!`),
  error => console.error(error)
);

Output:

> Fetching #444
> Fetching #1
> Fetching #2
> Fetching #3
> Fetching #4
> Fetching #5
#1,#2,#3,#444,#4,#5 DONE!

StackBlitz

  • Related