Cómo atrapar la excepción correctamente de http.request ()?

Parte de mi código:

import {Injectable} from 'angular2/core'; import {Http, Headers, Request, Response} from 'angular2/http'; import {Observable} from 'rxjs/Observable'; import 'rxjs/add/operator/map'; @Injectable() export class myClass { constructor(protected http: Http) {} public myMethod() { let request = new Request({ method: "GET", url: "http://my_url" }); return this.http.request(request) .map(res => res.json()) .catch(this.handleError); // Trouble line. // Without this line code works perfectly. } public handleError(error: Response) { console.error(error); return Observable.throw(error.json().error || 'Server error'); } } 

myMethod() produce una excepción en la consola del navegador:

EXCEPCIÓN ORIGINAL: TypeError: this.http.request (…). Map (…). Catch no es una función

Quizás puedas intentar agregar esto en tus importaciones:

 import 'rxjs/add/operator/catch'; 

También puedes hacer:

 return this.http.request(request) .map(res => res.json()) .subscribe( data => console.log(data), err => console.log(err), () => console.log('yay') ); 

Por comentarios:

EXCEPCIÓN: TypeError: Observable_1.Observable.throw no es una función

Del mismo modo, para eso, puede usar:

 import 'rxjs/add/observable/throw'; 

Nuevo servicio actualizado para usar HttpClientModule y RxJS v5.5.x :

 import { Injectable } from '@angular/core'; import { HttpClient, HttpErrorResponse } from '@angular/common/http'; import { Observable } from 'rxjs/Observable'; import { catchError, tap } from 'rxjs/operators'; import { SomeClassOrInterface} from './interfaces'; import 'rxjs/add/observable/throw'; @Injectable() export class MyService { url = 'http://my_url'; constructor(private _http:HttpClient) {} private handleError(operation: String) { return (err: any) => { let errMsg = `error in ${operation}() retrieving ${this.url}`; console.log(`${errMsg}:`, err) if(err instanceof HttpErrorResponse) { // you could extract more info about the error if you want, eg: console.log(`status: ${err.status}, ${err.statusText}`); // errMsg = ... } return Observable.throw(errMsg); } } // public API public getData() : Observable { // HttpClient.get() returns the body of the response as an untyped JSON object. // We specify the type as SomeClassOrInterfaceto get a typed result. return this._http.get(this.url) .pipe( tap(data => console.log('server data:', data)), catchError(this.handleError('getData')) ); } 

Servicio antiguo, que utiliza el HttpModule en desuso:

 import {Injectable} from 'angular2/core'; import {Http, Response, Request} from 'angular2/http'; import {Observable} from 'rxjs/Observable'; import 'rxjs/add/observable/throw'; //import 'rxjs/Rx'; // use this line if you want to be lazy, otherwise: import 'rxjs/add/operator/map'; import 'rxjs/add/operator/do'; // debug import 'rxjs/add/operator/catch'; @Injectable() export class MyService { constructor(private _http:Http) {} private _serverError(err: any) { console.log('sever error:', err); // debug if(err instanceof Response) { return Observable.throw(err.json().error || 'backend server error'); // if you're using lite-server, use the following line // instead of the line above: //return Observable.throw(err.text() || 'backend server error'); } return Observable.throw(err || 'backend server error'); } private _request = new Request({ method: "GET", // change url to "./data/data.junk" to generate an error url: "./data/data.json" }); // public API public getData() { return this._http.request(this._request) // modify file data.json to contain invalid JSON to have .json() raise an error .map(res => res.json()) // could raise an error if invalid JSON .do(data => console.log('server data:', data)) // debug .catch(this._serverError); } } 

Yo uso .do() ( ahora .tap() ) para la depuración.

Cuando hay un error del servidor, el body del objeto Response que recibo del servidor que estoy usando (lite-server) contiene solo texto, de ahí la razón por la que uso err.text() arriba en lugar de err.json().error . Es posible que deba ajustar esa línea para su servidor.

Si res.json() genera un error porque no pudo analizar los datos JSON, _serverError no obtendrá un objeto Response , de ahí el motivo de la instanceof verificación.

En este plunker , cambie la url a ./data/data.junk para generar un error.


Los usuarios de cualquiera de los servicios deberían tener un código que pueda manejar el error:

 @Component({ selector: 'my-app', template: '
{{data}}
{{errorMsg}}
` }) export class AppComponent { errorMsg: string; constructor(private _myService: MyService ) {} ngOnInit() { this._myService.getData() .subscribe( data => this.data = data, err => this.errorMsg = err ); } }

Las funciones RxJS necesitan ser importadas específicamente. Una manera fácil de hacerlo es importar todas sus características con import * as Rx from "rxjs/Rx"

Luego asegúrese de acceder a la clase Observable como Rx.Observable .

en la última versión del uso angular4

 import { Observable } from 'rxjs/Rx' 

importará todas las cosas requeridas.