13

Is there a way to map not only the successful response but also the error?

I want to get a modified error in the subscribe function

request.subscribe(
    response => {
        this.user = response;
    },
    error => {
        this.error = error;
    }
);

I already tried this

let request = this.http.put(url, JSON.stringify(user))
.map(
    response => response.json(),
    error => this.handleError(error) // returns a string
);

but handleError is never getting executed.

Thanks in advance.

gerric
  • 2,297
  • 1
  • 14
  • 32

1 Answers1

17

To map the result of error response, you need to use the catch operator:

let request = this.http.put(url, JSON.stringify(user)).map(
            response => response.json())
          .catch(
            error => this.handleError(error)
        );

The callback specified in the map operator is only called for successful responses.

If you want to "map" the error, you could use something like that:

this.http.get(...)
       .map(...)
       .catch(res => Observable.throw(res.json())

In this case, the mapped error will be provided to the callback defined in the second parameter of the subscribe method.

Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Thank you, this works. One more small question: Instead of mapping the succesful response I just want to execute a function (void) but still want `catch` to work like above. How can I achieve this? – gerric Mar 01 '16 at 08:19
  • You're free to do what you want in the `catch` callback: `.catch(res => { this.handleError(res); }` – Thierry Templier Mar 01 '16 at 08:37
  • Sorry my question was unclear, I want sth like a additional subscription, but only on success, that returns `Observable`. If I do `.map(res => doSomething():void` it will return `Observable`. – gerric Mar 01 '16 at 08:53
  • No worries! Perhaps the `do` operator to execute processing in an imperative way (not part of the data flow): `.do(res => { doSomething(res); })` – Thierry Templier Mar 01 '16 at 08:58
  • Does the generic type of error have to be the same as the one of response, or can I achieve `res: Response` and `error: any`? – gerric Mar 01 '16 at 09:30
  • In fact no. You're free to return what you want for error. It's different things... – Thierry Templier Mar 01 '16 at 09:33
  • `Observable.throw()` now returns an `ErrorObservable`. How can I get the old behaviour back? – gerric Mar 03 '16 at 13:20
  • You mean not ending the processing chain but continuing to receive events? – Thierry Templier Mar 03 '16 at 13:22
  • `Argument of type '(err: any) => ErrorObservable' is not assignable to parameter of type '(err: any, source: Observable, caught: Observable) => Observable'. Type 'ErrorObservable' is not assignable to type 'Observable'.` – gerric Mar 03 '16 at 13:24
  • On which line of your code do you get this error? – Thierry Templier Mar 03 '16 at 13:29
  • 2
    on `.catch(err => Observable.throw(this.handle(err)))` – gerric Mar 03 '16 at 13:31
  • With RxJS v6+ the syntax will be a bit different: `httpClient.get(...).pipe(catchError(error => throwError(error.error)))` – Daniel Kucal Oct 04 '20 at 11:59