3

I have my HTTP calls inside a service as it should be, and in that service I inyect another service for error notifications.

For some reason, if I make the service notification call inside the catchError pipe it works fine, but if I make it inside an error handler function it doesn't work, and not only that, the rest of the code inside the error handler is interrupted.

Example:

// error message handler
// can not be used inside handleError()
private errorMessageGrowl() {
  this.messageService.add({
      severity: 'error',
      summary: 'Service Error',
      detail: 'An error has occurred'
  });
}

// error handler
private handleError(error: HttpErrorResponse) {

    // this works fine
    console.log('FLAG 1');

    // THIS DOES NOT WORK
    this.errorMessageGrowl();

    // THIS IS NEVER CALLED
    console.log('FLAG 2');

    // return an ErrorObservable with a user-facing error message
    return new ErrorObservable(
        'Something bad happened; please try again later.');
}

// http request
getService(): Observable<any> {

    return this.http.get<any>('./../../assets/data/example.json')
        .pipe(
            retry(4),
            catchError(this.handleError)
        );
}

It retries 4 times, it shows the "FLAG 1" log in console once, but the errorMessageGrowl() and the "FLAG 2" log is never shown.

Now, if I remove the notifications service from the error handler and call it inside the catchError pipe, it works perfectly:

// error handler
private handleError(error: HttpErrorResponse) {

    // this works fine
    console.log('FLAG');

    // return an ErrorObservable with a user-facing error message
    return new ErrorObservable(
        'Something bad happened; please try again later.');
}

// http request
getService(): Observable<any> {

    return this.http.get<any>('./../../assets/data/example.json')
        .pipe(
            retry(4),
            catchError((error) => {
                this.handleError(error);

                // it works outside handleError()
                this.errorMessageGrowl()
            })
        );
}
David Prieto
  • 2,239
  • 4
  • 32
  • 51

3 Answers3

5

By writing

catchError(this.handleError)

You lose your context (this doesn't point to the thing you expect)

replace it with

catchError((...args) => this.handleError(...args))
// OR
catchError(this.handleError.bind(this))
  • I feel so silly. I'll accept this answer because you were first. – David Prieto Aug 29 '18 at 13:14
  • @DavidPrieto no need to, I wanted to help you before closing your question (the one provided is rather long), I've already marked it as duplicate. –  Aug 29 '18 at 13:15
2

You're losing context inside catch. You need to call bind or use fat arrow function to call handleError()

catchError(this.handleError.bind(this)
// or
catchError((err) => this.handleError(err))
1

That is probably because you are loosing the context of this. Use bind() to retain that

// http request

getService(): Observable<any> {

    return this.http.get<any>('./../../assets/data/example.json')
        .pipe(
            retry(4),
            catchError(this.handleError.bind(this))
        );
}
Amit Chigadani
  • 28,482
  • 13
  • 80
  • 98