How to throw error from RxJS map operator (angular)
Even though this question is already answered, I'd like to share my own approach (even though its only slightly different from above).
I would decide what is returned separate from the mapping and vice versa. I'm not sure what operator is best for this so I'll use tap
.
this.httpPost.pipe(
tap(res => {
if (!res.bearerToken) {
throw new Error('Valid token not returned');
}
}),
map(res => this.saveJwt(res.bearerToken)),
);
Just throw the error inside the map()
operator. All callbacks in RxJS are wrapped with try-catch blocks so it'll be caught and then sent as an error
notification.
This means you don't return anything and just throw the error:
map(res => {
if (res.bearerToken) {
return this.saveJwt(res.bearerToken);
} else {
throw new Error('Valid token not returned');
}
})
The throwError()
(former Observable.throw()
in RxJS 5) is an Observable that just sends an error
notification but map()
doesn't care what you return. Even if you return an Observable from map()
it'll be passed as next
notification.
Last thing, you probably don't need to use .catchError()
(former catch()
in RxJS 5). If you need to perform any side effects when an error happens it's better to use tap(null, err => console.log(err))
(former do()
in RxJS 5) for example.
Jan 2019: Updated for RxJS 6
If you feel like throw new Error()
seems un-observable-like you can use return throwError(...)
with switchMap
instead of map
(the difference being switchMap
has to return a new observable instead of a raw value):
// this is the import needed for throwError()
import { throwError } from 'rxjs';
// RxJS 6+ syntax
this.httpPost.pipe(switchMap(res => {
if (res.bearerToken) {
return of(this.saveJwt(res.bearerToken));
}
else {
return throwError('Valid token not returned'); // this is
}
});
or more concisely:
this.httpPost.pipe(switchMap(res => (res.bearerToken) ?
of(this.saveJwt(res.bearerToken)) :
throwError('Valid token not returned')
));
The behavior will be the same, it's just a different syntax.
You're literally saying 'switch' from the HTTP observable in the pipe to a different observable, which is either just 'wrapping' the output value, or a new 'error' observable.
Don't forget to put of
or you'll get some confusing error messages.
Also the beauty of 'switchMap' is that you can return a whole new 'chain' of commands if you wanted to - for whatever logic needs to be done with saveJwt
.