简体   繁体   中英

RxJS/Angular 11 wait for 2 observables complete and errors handling

I need wait for two requests (observables) and do some things. What i need:

  1. Wait for requests (observables) end
  2. If one of them failed - display one error
  3. If both of them failed - display second error
  4. If first success - do some things
  5. If second success - do some things

i can combine 4 and 5 if that matter for errors handling.

I tried to use forkJoin but it fails at all if one of requests failed.
I tried to use concat but it works the same as forkJoin
I tried to use combineLatestWith but it doesn't display errors at all as combineLatest
Finally i tried to use next:

const firstRequest$ = this.doFirstRequest(searchRequest);
const secondRequest$ = this.doSecondRequest(searchRequest);
combineLatest([firstRequest$, secondRequest$]).subscribe(([res1, res2]) => {
  console.log(res1, res2);
}, err => {
  console.log(err);
});

and now i got only both success results and didn't get any error What im missing?

catch your errors at the request level and transform them into something usable:

const firstRequest$ = this.doFirstRequest(searchRequest).pipe(
  catchError(error => of({error})) 
);
const secondRequest$ = this.doSecondRequest(searchRequest).pipe(
  catchError(error => of({error}))
);
forkJoin([firstRequest$, secondRequest$]).subscribe(([res1, res2]) => {
  if (res1.error && res2.error) {
    // both failed
  } else if (res1.error || res2.error) {
    // one failed
  }
  if (!res1.error) {
    // req 1 success 
  }
  if (!res2.error) {
    // req 2 success
  }
  // whatever you need to do now that they're both done
}, err => {
  // can't get here now
});
  1. You need to use forkJoin for this use case, See ForkJoin docs .

  2. Add catchError operator to the first stream to handle the first request

  3. Add another catchError operator to the second stream to handle it

  4. Add tap operator to the first stream 1

  5. Add another tap operator to the first stream 2

const firstRequest$ = this.doFirstRequest(searchRequest).pipe(
  tap(() => {
    // DO SOMETHING STREAM 1 REGARDLESS OF STREAM 2
  }),
  catchError((e => {
    console.error('Error from stream 1', e);
    return EMPTY;
  });
);

const secondRequest$ = this.doFirstRequest(searchRequest).pipe(
  tap(() => {
    // DO SOMETHING STREAM 2 REGARDLESS OF STREAM 1
  }),
  catchError((e => {
    console.error('Error from stream 2', e);
    return EMPTY;
  });
);

forkJoin([firstRequest$, secondRequest$]).subscribe(([res1, res2]) => {
  console.log('All done');

  if (res1) {
    // DO SOMETHING STREAM 1 AFTER ALL STREAMS ARE DONE
  }

  if (res21) {
    // DO SOMETHING STREAM 2 AFTER ALL STREAMS ARE DONE
  }
});

I had a case where one request normally takes much longer than the other, so in the success case I don't want to have to wait for both requests to finish before continuing. As soon as one request finishes, I want to show the received data to the user. But the error handling needed to be different if both requests failed, than if just one failed or when both succeeded.

So I did this:

getRequestASucceeded$ = new ReplaySubject<boolean>(1);

this.getRequestA()
    .subscribe( dataA => {
       this.getRequestASucceeded$.next(true);
       // continue with dataA
     },
     (err: HttpErrorResponse) => {
        this.getRequestASucceeded$.next(false);
      }
   );

this.getRequestB()
    .subscribe( dataB => {
       
       // continue with dataB

       this.getRequestASucceeded$.subscribe( hasSucceeded => {
          if (hasSucceeded) {
            // Both Request succeeded
          else {
            // RequestA failed, RequestB succeeded
          }
     },
     (err: HttpErrorResponse) => {
        
        this.getRequestASucceeded$.subscribe( hasSucceeded => {
          if (hasSucceeded) {
            // RequestA succeeded, RequestB failed
          else {
            // Both Request failed
          }
      }
   );

The Errors are only processed after both requests finished, but the individaul data can get processed right away.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM