简体   繁体   中英

Handling errors thown by promise in observable created by from()

I'm trying to use the AngularFire library in an Angular application. Some of the AngularFire calls return promises, and I'd like to handle them as observables instead for consistency throughout the app. I'm using rxjs v6

Using from() works well and gives the expected behaviour except when errors occur.

If the promise throws an exception, the observable doesn't seem to see it and a stack trace gets dumped in the console saying Error: Uncaught (in promise) .

My first attempt

The AngularFire call that returns the promise:

deleteCampaign(id: string) {
  return from(this.campaignCollection.doc(id).delete());
}

The calling code:

    deleteCampaign(id: string) {
        return this.dataStorageService.deleteCampaign(id)
        .pipe(
            catchError(
                err => {
                    console.log('error when deleting campaign');
                    console.log(err);
                    return throwError(err);
                }
            )
        );
    }

In this instance, I get the stack trace in the console and the catchError never fires.

My second attempt

I added a catch to the promise inside the from , and then tried rethrowing the error as an observable so it looked like this:

    deleteCampaign(id: string) {
        return from(this.campaignCollection.doc(id).delete().catch(
            err => {
                throwError(err);
            }
        ));
    }

My third attempt

Much like the second attempt, but I tried throwing a plain javascript error. This resulted in the same stack trace however, and it wasn't picked up by the observable either.

    deleteCampaign(id: string) {
        return from(this.campaignCollection.doc(id).delete().catch(
            err => {
                throw(err);
            }
        ));
    }

This stopped the stack trace happening, as now the promise was catching it, but the calling code still never sees the error.

Am I going about this the wrong way? I assumed that by using from() all of the error handling could occur in the observable, and I could leave the promise alone.

I need to be able to either: 1. Have no error handling code where the promise is returned and let the observable take care of it. 1. Have the promise catch block able to rethrow an error thats caught by the observable.


Here's the solution arrived at:

From the front end component, handle the passed error using the error callback in subscribe

  onDelete(id: string) {
    this.loadingCampaigns = true;
    this.campaignService.deleteCampaign(id).subscribe(
      _ => {},
      err => {
        console.log('error detection from the component');
      }
    );
  }

From the campaign service, tap() the error so it can be logged or otherwise:

    deleteCampaign(id: string) {
        return this.dataStorageService.deleteCampaign(id)
        .pipe(
            tap(null, () => {console.log('tapped the error');} ),
        );
    }

Finally, from the data storage component do nothing at all:

    deleteCampaign(id: string) {
        return from(this.campaignCollection.doc(id).delete());
    }

You can attach an error callback to Observable.subscribe() .

Rx.Observable.from(Promise.reject('Boo!'))
    .subscribe(val => {
        console.log('success');
    },
    err => {
        console.log(err);
    });
// Boo!
deleteCampaign(id: string) {
  return from(this.campaignCollection.doc(id).delete()).pipe(catchError(err=>{
      return throwError(err);
    }))
}

deleteCampaign(myid).susbcribe(res=>{
    console.log(res);
},error=>{
    console.log(error)
})

I put an example using ng-bootstrap modal -that return a promise when open the modal- to convert to a Observable in this stackblitz

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