Martin Andersen
Martin Andersen

Reputation: 2740

RxJS Wait for all observables to finish with data from the first call

I need to fetch data from a service. Then I need to loop through the data and fetch data with the id's I got from the first call.

My goal is to optimise Angular bindings performance by calling markForCheck() on ChangeDetectorRef when all data are loaded.

This is my current code. It's get the job done. But the call to markForCheck() is done before all data is loaded.

 this.subs.push(
  this.supplierService
    .supplier(this.supplierId)
    .pipe(
      tap(supplier => {
        this.subs.push(
          of(supplier.employees.map(emp => emp.authId))
            .pipe(
              mergeMap(ids => ids.map(id => this.authRegisterService.lookupId(id))),
              mergeMap(res => res)
            )
            .subscribe(
              result => {
                this.authRegs.push(result);
              },
              error => {
                this.toastr.error(error);
                return EMPTY;
              }
            )
        );
      }),
      tap(supplier => {
        this.subs.push(this.cvrService.getCompany(supplier.cvr).subscribe(cvr => (this.cvr = cvr)));
      }),
      tap(supplier => {
        this.subs.push(
          of(supplier.locations.map(loc => loc.sorId))
            .pipe(
              mergeMap(ids => ids.map(id => this.sorService.getLocation(id))),
              mergeMap(res => res)
            )
            .subscribe(sor => {
              this.sors.push(sor);
            })
        );
      })
    )
    .subscribe(supplier => {
      this.supplier = supplier;
      this.supplierStatusLabel = SupplierStatusNames.get(supplier.status);
      this.cd.markForCheck();
    })
);

I read the documentation for forkJoin but I don't know how to combine it with the first call. All input are much appreciate.

Upvotes: 0

Views: 3638

Answers (1)

Asfo
Asfo

Reputation: 413

You don't need forkJoin, you need mergeMap or concatMap, forkJoin is bad normally, why?, because if one request fails, then, everything else fails.

mergeMap and concatMap if one of ten requests for example fails, the other nine keeps trying to finish.

The difference between mergeMap and concatMap is the way they does the requests, in mergeMap they are sent to the server in "one push", I mean, lets think that you want to pull 10 dates, mergeMap then do the request for the 10 dates without waiting the previous one to finish while concatMap waits for the previous to finish to add a new request to the queue.

Here you have an example of "how to use concatMap, mergeMap and forkJoin": https://angular-bojdob.stackblitz.io

I wrote a medium post but is on spanish, but there is a really nice medium post about this too: Here it is in spanish (mine): https://medium.com/@asfo/usando-concatmap-mergemap-y-forkjoin-en-angular-para-peticiones-http-c70f65df54af

Here it is from Tomas (english): https://blog.angularindepth.com/practical-rxjs-in-the-wild-requests-with-concatmap-vs-mergemap-vs-forkjoin-11e5b2efe293

Upvotes: 3

Related Questions