Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

rxjs - Angular 6 : Error handling with forkJoin

I am not sure how to get exception message for specific api call while using forkJoin

I have code written as below

    reqs = [];
    if (shouldUpdatePhone) {
       reqs.push(this.customerService.updatePhone(phoneUpdateRequest))
    }
    if (shouldUpdateAddress) {
       reqs.push(this.customerService.updateAddress(addressUpdateRequest))
    }

    forkJoin(reqs).subscribe(result => {
       console.log('result :', result);

    }, error => {
      //How to get error message for particular api call?
});

In case one/both api failed due to some reason. How should i decide which api throws an exception.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

there's a way to handle errors with forkJoin that doesn't block you from using this operator. The key is actually part of the other answer.

Yes, forkJoin will complete on first error and you kinda can't know from which observable it came, but if you handle errors inside the inner observables you can easily achieve that.

Consider this (minified) part of your code, mixed with @Explosion Pills answer:

reqs: Observable<any>[] = [];
if (shouldUpdatePhone) {
  reqs.push(
    this.service.updatePhone(phone)
      .pipe(
        catchError((err) => {
          // Handle specific error for this call
          return of(undefined)),
        }
      )
  );
}
if (shouldUpdateAddress) {
      reqs.push(
        this.service.updateAddress(address)
          .pipe(
            catchError((err) => {
              // Handle specific error for this call
              return of(undefined)),
            }
          )
      );
    }

And then, for your forkJoin:

forkJoin(reqs).subscribe(result => console.log(result));

Now consider that both API calls return an object like, respectively, {phone: string} and {address: string}. Your result will be:

[{phone: '123-456'}, {address: 'Happy Street, 123'}]

But ok, that's basic forkJoin, where's the error handling part?
Consider that one of your calls failed, the returned error contains a status code and a message and you want to know 'em both.

As I said, forkJoin won't complete if you handle error inside the inner observable, that's why we have

  .pipe(
    catchError((err) => {
      // Handle specific error for this call
      return of(undefined)),
    }
  )

If your first call (updatePhone) fails, your result would be

[undefined, {address: 'Happy Street, 123'}]

Because you didn't let the observable die and, upon error, returned a new Observable with return of(undefined).

This opens you the possibility to handle errors like this (inside catchError):

catchError((err) => {
  if (err.status === 409) {
    // do something
  }
  return of(undefined)),
}

Or like this

...
catchError((err) => {
  return of({error: err, isError: true})),
}
...
forkJoin(...).subscribe(result => {
  result.forEach(r => {
    if (r.isError) {
      // do something
    }
  });
});

All your API calls will complete and you can either handle it on the go or wait for all of them to return and handle only the ones that returned error, with this you can get any information that your error could provide to you and handle it specifically.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...