Angular2 HTTP response processing

I only have a question about structuring and processing responses from HTTP requests in the service. I am using Angular2.alpha46 Typescript (just started testing this that I love ... Ps .. Thanks to all the people who worked on this and contribute through github)

So do the following:

Login-form.component.ts

import {Component, CORE_DIRECTIVES, FORM_DIRECTIVES} from 'angular2/angular2'; import {UserService} from '../../shared/service/user.service'; import {Router} from 'angular2/router'; import {User} from '../../model/user.model'; import {APP_ROUTES, Routes} from '../../core/route.config'; @Component({ selector: 'login-form', templateUrl: 'app/login/components/login-form.component.html', directives: [CORE_DIRECTIVES, FORM_DIRECTIVES] }) export class LoginFormComponent { user: User; submitted: Boolean = false; constructor(private userService:UserService, private router: Router) { this.user = new User(); } onLogin() { this.submitted = true; this.userService.login(this.user, () => this.router.navigate([Routes.home.as])) } } 

from this component, I import my userService, in which my HTTP request will be stored, in order to log into the user's system, the service looks like this:

user.service.ts

 import {Inject} from 'angular2/angular2'; import {Http, HTTP_BINDINGS, Headers} from 'angular2/http'; import {ROUTER_BINDINGS} from 'angular2/router'; import {User} from '../../model/user.model'; export class UserService { private headers: Headers; constructor(@Inject(Http) private http:Http) { } login(user: User, done: Function) { var postData = "email=" + user.email + "&password=" + user.password; this.headers = new Headers(); this.headers.append('Content-Type', 'application/x-www-form-urlencoded'); this.http.post('/auth/local', postData, { headers: this.headers }) .map((res:any) => res.json()) .subscribe( data => this.saveJwt(data.id_token), err => this.logError(err), () => done() ); } saveJwt(jwt: string) { if(jwt) localStorage.setItem('id_token', jwt) } logError(err: any) { console.log(err); } } 

What I want to do is be able to handle the response that the call returns after the HTTP request. For example, if the user credentials are invalid, I pass the 401 response back from the backend. My question is where is the best way to process the response and return the result back to the component from which I called the method, so I can manipulate the view to show a success message or display an error message.

At the moment, in my service under the login, I do not currently process the response. I'm just making a callback back to the original component, but I feel this is not the right way to do this? Can someone shed light on what they will do in this typical scenario? I would process the response in the first parameter of the subscription function, for example:

  login(user: User, done: Function) { var postData = "email=" + user.email + "&password=" + user.password; this.headers = new Headers(); this.headers.append('Content-Type', 'application/x-www-form-urlencoded'); this.http.post('/auth/local', postData, { headers: this.headers }) .map((res:any) => res.json()) .subscribe( (data) => { // Handle response here let responseStat = this.handleResponse(data.header) // Do some stuff this.saveJwt(data.id_token); // do call back to original component and pass the response status done(responseStat); }, err => this.logError(err) ); } handleResponse(header) { if(header.status != 401) { return 'success' } return 'error blah blah' } 

Is the callback in this case or can it be handled better with an observable or promise?

The end of what I ask is ... What is the best way to process the response from the HTTP response and process the status in the form view from user.service.ts back to login-form.component.ts

+50
angular typescript
Nov 26 '15 at 15:09
source share
3 answers

Update alpha 47

As with alpha-47, the answer below (for alpha-46 and below) is no longer required. The Http module now automatically processes the returned errors. So now as easy as it should

 http .get('Some Url') .map(res => res.json()) .subscribe( (data) => this.data = data, (err) => this.error = err); // Reach here if fails 

Alpha 46 and below

You can process the response in map(...) , before subscribe .

 http .get('Some Url') .map(res => { // If request fails, throw an Error that will be caught if(res.status < 200 || res.status >= 300) { throw new Error('This request has failed ' + res.status); } // If everything went fine, return the response else { return res.json(); } }) .subscribe( (data) => this.data = data, // Reach here if res.status >= 200 && <= 299 (err) => this.error = err); // Reach here if fails 

Here is plnkr with a simple example.

Please note that in the next version this will not be necessary, because all status codes below 200 and above 299 will automatically generate an error, so you do not have to check them yourself. See commit for more details.

+69
Nov 26 '15 at 15:37
source

in angular2 2.1.1 I was not able to catch the exception using the (data), (error) pattern, so I implemented it with .catch (...).

Good, because it can be used with all other Observable chains, such as .retry.map, etc.

 import {Observable} from 'rxjs/Rx'; Http .put(...) .catch(err => { notify('UI error handling'); return Observable.throw(err); // observable needs to be returned or exception raised }) .subscribe(data => ...) // handle success 

from the documentation :

Returns

(Observed): An observable sequence containing elements from consecutive source sequences until the source sequence completes successfully.

+7
Nov 22 '16 at 10:50
source

Service:

 import 'rxjs/add/operator/map'; import { Http } from '@angular/http'; import { Observable } from "rxjs/Rx" import { Injectable } from '@angular/core'; @Injectable() export class ItemService { private api = "your_api_url"; constructor(private http: Http) { } toSaveItem(item) { return new Promise((resolve, reject) => { this.http .post(this.api + '/items', { item: item }) .map(res => res.json()) // This catch is very powerfull, it can catch all errors .catch((err: Response) => { // The err.statusText is empty if server down (err.type === 3) console.log((err.statusText || "Can't join the server.")); // Really usefull. The app can't catch this in "(err)" closure reject((err.statusText || "Can't join the server.")); // This return is required to compile but unuseable in your app return Observable.throw(err); }) // The (err) => {} param on subscribe can't catch server down error so I keep only the catch .subscribe(data => { resolve(data) }) }) } } 

In the application:

 this.itemService.toSaveItem(item).then( (res) => { console.log('success', res) }, (err) => { console.log('error', err) } ) 
+1
Aug 20 '17 at 12:20
source



All Articles