2

I have an array of applications and I want each application to have a new property called Blobs. I have to make a new HTTP request to get Blobs for every single application and I use switchMap for that. However, for some reason, it only emits the last application and not every single one.

(bad explanation I know but you'll get the idea when you read the code)

this.serviceOne.getAllApplications(visitId).pipe(
    switchMap((applications) => from(applications)),
    switchMap((application) => {
        console.log("successfully logs every application in applications array");
        return forkJoin([
            of(application),
            this.blobsService.getBlobBs({
                visitId,
                applicationId: application.id,
            }),
        ]);
    }),
    map(([application, blobs]) => {
        console.log("only logs on last emitted application");
        return { ...application, blobs };
    }),
    toArray()
)

It returns an array with only the last element in it (blobs property is correctly added in that last object tho.)

Whenever I change forkJoin to this:

return forkJoin([
    of(application) ,
    of([])
]);

It starts to work as it should.

Get Blobs:

getBlobBs(identifier: IIdentifier): Observable<BlobItem[]> {
    return this.http.get<BlobItem[]>(
        'service url goes here'
    )
}
navnath
  • 3,548
  • 1
  • 11
  • 19
Vazhaabdu
  • 23
  • 3

2 Answers2

2

Use mergeMap instead of switchMap.

switchMap is cancelling all requests and only the last is processed.

switchMap : Cancels the current subscription/request when new request arrives. Used for cancelable requests like searches

mergeMap : Runs subscriptions/requests in parallel. Do not cancel the current request. Use when order is not important

concatMap : Runs subscriptions/requests in order and is less performant. Use when order is important. It processes all requests/subscriptions but in sequential order.

I think in your case mergeMap is suitable since you want to provide a response to all requests.

navnath
  • 3,548
  • 1
  • 11
  • 19
0

This is a prety common pattern with RxJS. You can do it without forkJoin to avoid creating and destructing an intermediate array.

this.serviceOne.getAllApplications(visitId).pipe(
  mergeMap(applications => applications),

  mergeMap(application => 
    this.blobsService.getBlobBs({
      visitId,
      applicationId: application.id,
    }).pipe(
      takeLast(1),
      map(blobs => ({...application, blobs}))
    )
  ),
  
  toArray()
)
Mrk Sef
  • 7,557
  • 1
  • 9
  • 21