Reputation: 53
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());
}
Upvotes: 5
Views: 4040
Reputation: 57939
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
Upvotes: 0
Reputation: 907
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!
Upvotes: 5