Don't worry if you don't have a specific type to assign to T
, because if you don't pass result
to the handleError
function, T
will default to being undefined
. Undefined not only represents a value but also its own type.
An interesting point to consider is that the handleError
function doesn't actually create the observable itself. Instead, it returns a function that generates the observable each time it is called.
private handleError<T> (operation = 'operation', result?: T) {
// This function is returned:
return (error: any): Observable<T> => {
log(`${operation} failed: ${error.message}`);
return of(result as T);
};
}
Therefore, when we use handleError
with an operation
, we receive a function that can be repeatedly invoked with errors, maintaining the same name and description for each call. It's simply a way to standardize error handling through a simple function. The optional parameter result
now starts to make more sense. For example:
const handler = this.handleError('Fetching stuff');
const err1 = new Error('something went wrong');
const err2 = new Error('something else went wrong');
handler(err1); // "Fetching stuff failed: something went wrong"
handler(err2); // "Fetching stuff failed: something else went wrong"
Similarly, by providing a result
value to handleError
, it will be used consistently for all calls to the generated function. This is most beneficial when the functions created by handleError
are utilized outside of the defining class. By exposing a function that returns observables with a predetermined value known by the class, additional information can be communicated to the calling code after handling the error.
Update
In the following snippet from the link provided, we can observe how handleError
is effectively implemented:
/** GET heroes from the server */
getHeroes (): Observable<Hero[]> {
return this.http.get<Hero[]>(this.heroesUrl)
.pipe(
tap(_ => this.log('fetched heroes')),
catchError(this.handleError<Hero[]>('getHeroes', []))
);
}
This showcases the usage of the function as an error handler for unsuccessful http requests. Here, result
is represented by an empty array serving as the default value for an array of heroes (Hero[]
) which the getHeroes
method aims to deliver.
Applied in this manner, this approach demonstrates a currying technique that seamlessly integrates with the observable catchError
operator. The operator leverages the returned error handler, executing it whenever an error occurs.