2
votes

I'm running the Angular tutorial and I can't understand what is actually happening in one section. I've found some examples from searching, but nothing specifically answers this question. Here is the code:

getHeroes (): Observable<Hero[]> {
  return this.http.get<Hero[]>(this.heroesUrl)
    .pipe(
      catchError(this.handleError('getHeroes', []))
    );
} 

Next is the error handler it calls:

/**
 * Handle Http operation that failed.
 * Let the app continue.
 * @param operation - name of the operation that failed
 * @param result - optional value to return as the observable result
 */
private handleError<T> (operation = 'operation', result?: T) {
  return (error: any): Observable<T> => {

    // TODO: send the error to remote logging infrastructure
    console.error(error); // log to console instead

    // TODO: better job of transforming error for user consumption
    this.log(`${operation} failed: ${error.message}`);

    // Let the app keep running by returning an empty result.
    return of(result as T);
  };
}

I read the documentation I could find on catchError. I'm new to Typescript and really enjoying it though. Okay, so the question is why I'm passing a function to catchError, which then returns another function. Specifically, my question is about the embedded function return (error: any): Observable<T> => {

Why is handleError returning a function with fat arrow notation instead of just an observable of type T? How is the error parameter of the embedded function receiving data?

I think it has something to do with the fact that handleError is called, which returns a function. So in essence catchError receives that embedded function with the parameter error, but it also has the variables operation and result? in the same scope so it can work with those. catchError then passes the data to the parameter error and returns an observable T.

RXJS Reference defines catchError as:

catchError<T, R>(selector: (err: any, caught: Observable<T>) =>
ObservableInput<R>): OperatorFunction<T, T | R>

But it's hard for me to decipher why it's being passed a function as all the example have.

1

1 Answers

5
votes

Your assumptions are correct: the handleError function gets called first which itself creates a function for handling the error. There are a couple of other ways to write this that might help clarify a bit more:

// write the function inline:
catchError(error => {
  console.error(error);
  this.log(`getHeroes failed: ${error.message}`);
  return of([]);
});

// call `handleError` first to get the error handler and pass it as a variable.
const errorHandler = this.handleError('getHeroes', []);
return this.http.get<Hero[]>(this.heroesUrl)
  .pipe(catchError(errorHandler));

catchError requires a function passed to it that returns an Observable to continue the observable stream. The returned observable is created by of. The type T allows the error handler to determine the type of the values emitted by the Observable based on the fallback argument you've passed in.