Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Observable Map function not running (Angular2, http)

Update

The issue seems to be that the map function is not run on a "failed" request. This means that if the API I'm talking to returns a 422 Validation Failed error (or other 4xx errors) Angular will treat this as a failure and cause the Observer to run the subscribed error callback, skipping the map function in the process.

Is it possible to force Angular to treat certain 4xx errors as successful requests, or force the map function to run even when an Observable returns an error?


I have the following code running in my Angular2 app:

import {Injectable} from "angular2/core";
import {Observable} from "rxjs/Rx";
import {Http, Headers, ResponseOptions, Response} from "angular2/http";
import 'rxjs/add/operator/map';

...

public login (email : string, password : string) {
    return this.http.post(_endPoint + '/auth/login/', JSON.stringify({
        email: email,
        password: password
    }), {
        headers: new Headers({
            'Content-Type': 'application/json'
        })
    })
    .map (res => {
        let data = res.json();
        console.log(data);
        return data;
    });
}

The code is executing fine, with the exception that the map function is not fired. I am not getting any errors, and have tried running the code both with and without the import 'rxjs/add/operator/map' with the same result. I have also tried a simpler map function .map (res => res.json());.

In both cases I expect the result returned in the .subscribe() function to be the JSON response, but instead I am getting the raw response.

Edit: Added a screenshot of the request data, and the response

Request details

Response:

[{"field":"email","message":"Email or password incorrect."},{"field":"password","message":"Email or password incorrect."}]

I've also tested it on a completely successful request (Status Code: 200) and the map function appears to be working fine. So I guess it only runs when a successful response is returned. Is there a way to get it to run regardless, or specify additional status codes that it should run on?

like image 964
Tam Avatar asked Jan 18 '16 13:01

Tam


1 Answers

As discussed with comments, the map method isn't called because the response contains a 422 status code, i.e. an error. So the catch method is directly called.

If you need to extract the JSON content corresponding to the error you could try something like that in your service:

getCompanies() {
  return this.http.get('https://angular2.apispark.net/v1/companies1/', {
    headers: headers
  }).map(res => res.json()).catch(err => Observable.throw(err.json());
}

Now in the component that calls the service, you will be able to subscribe. The second parameter will be called in your case with the JSON content of the response:

service.getCompanies().subscribe(
  data => console.log('data = '+data),
  err => console.log('err = '+JSON.stringify(err, null, 2)), // <---
  () => console.log('complete')
);

The printed content is:

err = {
  "code": 404,
  "description": "The server has not found anything matching the request URI",
  "reasonPhrase": "Not Found"
}

Hope it helps you, Thierry

like image 195
Thierry Templier Avatar answered Nov 17 '22 00:11

Thierry Templier