In most of my API calls I use this pattern:
call server and pipe result
Check for error and throw if needed
map results from server
public getItems() : Observable<Item[]> {
return this.http.get<Item[]>>(environment.url + '/items').pipe(
catchError((error:any)=> throwError('Failed getting items')),
map((ret)=> this.mapResults(ret)));
}
Is there a way to merge the catchError and map operators to a single operator ?
Something like this:
catchErrorAndMap("Message in case of error",itemForMapping)
itemForMapping will go into the mapping function. something like this?
return this.http.get<Item[]>>(environment.url + '/items').pipe(
catchErrorAndMap('Failed getting items'),ret));
Yes. An RxJS operator is just a function. So, you can write your own RxJS operators.
There is an example here: https://netbasal.com/creating-custom-operators-in-rxjs-32f052d69457
In the section entitled: "Creating Operators from Existing Operators".
So you can create a catchErrorAndMap
function that you can then use as an operator.
Here is an example:
export function catchErrorAndMap(errorMessage): OperatorFunction<User[], User[]> {
return source =>
source.pipe(
catchError((error: any) => throwError(errorMessage)),
map(items => items.map(item => ({ ...item, name: item.name + "'s"} as User)))
);
}
This creates a function that takes in an Observable<User[]> and returns an Observable<User[]>. You'd need to modify it as needed for your project. (Probably Item[]).
It then pipes the source (which is the emitted item from the source stream) through the desired operators.
In this example, I used a map operation appropriate for my data. You could of course change it to your this.mapResults()
.
You'd call this operator just like any other pipe operator:
users$ = this.http
.get<User[]>(this.userUrl)
.pipe(catchErrorAndMap("Error Occurred"));