metodo ejemplo typescript angular

typescript - ejemplo - subscribe angular 5



Angular2 manejando la respuesta http (3)

Solo tengo una pregunta sobre la estructuración y el manejo de respuestas de solicitudes http dentro de un servicio. Estoy usando Angular2.alpha46 Typecript (Acabo de comenzar a probarlo, lo que me encanta ... Ps ... Gracias a todas las personas que han estado trabajando en él y contribuyendo a través de github)

Entonces toma lo siguiente:

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])) } }

desde este componente importo mi servicio de usuario que albergará mi solicitud http para iniciar sesión en el usuario, el servicio se ve así:

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); } }

Lo que quiero hacer es poder manejar la respuesta que devuelve la llamada después de la solicitud http. Por ejemplo, si las credenciales del usuario no son válidas, le devuelvo una respuesta 401 del backend. Mi pregunta es cuál es la mejor manera de manejar la respuesta y devolver el resultado al componente desde donde llamé al método para poder manipular la vista para mostrar el mensaje de éxito o mostrar un mensaje de error.

En este momento en mi servicio bajo inicio de sesión, actualmente no estoy manejando la respuesta, simplemente estoy devolviendo la llamada al componente original, pero siento que esta no es la forma correcta de hacerlo. ¿Alguien puede arrojar algo de luz sobre lo que haría en este escenario típico? ¿Manejaría la respuesta en el primer parámetro de la función de suscripción como:

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'' }

¿Está bien una devolución de llamada en este caso o se puede manejar mejor con una observación o una promesa?

Concluyendo lo que estoy preguntando es ... ¿Cuál es la mejor práctica para manejar la respuesta de la respuesta http y manejar el estado en la vista del formulario desde user.service.ts de nuevo a login-form.component.ts


El servicio :

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) }) }) } }

En la aplicación:

this.itemService.toSaveItem(item).then( (res) => { console.log(''success'', res) }, (err) => { console.log(''error'', err) } )


en angular2 2.1.1 No pude detectar la excepción usando el patrón (datos), (error), así que lo implementé usando .catch (...).

Es agradable porque se puede usar con todos los demás métodos encadenados Observables como .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

de la documentation :

Devoluciones

(Observable): una secuencia observable que contiene elementos de secuencias fuente consecutivas hasta que una secuencia fuente termina con éxito.


Actualización alfa 47

A partir de alpha 47, la respuesta a continuación (para alpha46 y abajo) ya no es necesaria. Ahora el módulo Http maneja automáticamente los errores devueltos. Así que ahora es tan fácil como sigue

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

Alpha 46 y abajo

Puede manejar la respuesta en el map(...) , antes de la 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

Aquí hay un plnkr con un ejemplo simple.

Tenga en cuenta que en la próxima versión esto no será necesario porque todos los códigos de estado por debajo de 200 y por encima de 299 arrojarán un error automáticamente, por lo que no tendrá que verificarlos usted mismo. Verifique este compromiso para más información.