Como capturar exceção corretamente de http.request ()?

Parte do meu 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() produz uma exceção no console do navegador:

EXCEÇÃO ORIGINAL: TypeError: this.http.request (…). Map (…). Catch não é uma function

Talvez você possa tentar adicionar isso em suas importações:

 import 'rxjs/add/operator/catch'; 

Você também pode fazer:

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

Por comentários:

EXCEÇÃO: TypeError: Observable_1.Observable.throw não é uma function

Da mesma forma, para isso, você pode usar:

 import 'rxjs/add/observable/throw'; 

Novo serviço atualizado para usar o HttpClientModule e o 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')) ); } 

Serviço antigo, que usa o HttpModule obsoleto:

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

Eu uso .do() ( agora .tap() ) para debugging.

Quando há um erro no servidor, o body do object Response que recebo do servidor que estou usando (lite-server) contém apenas texto, daí a razão pela qual eu uso err.text() acima, em vez de err.json().error . Você pode precisar ajustar essa linha para o seu servidor.

Se res.json() um erro porque não foi possível analisar os dados JSON, o _serverError não obterá um object Response , daí a razão para a instanceof verificação.

Neste plunker , mude o url para ./data/data.junk para gerar um erro.


Os usuários de qualquer serviço devem ter código que possa manipular o erro:

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

As funções RxJS precisam ser importadas especificamente. Uma maneira fácil de fazer isso é importar todos os seus resources com o import * as Rx from "rxjs/Rx"

Em seguida, certifique-se de acessar a class Observable como Rx.Observable .

na última versão do uso angular4

 import { Observable } from 'rxjs/Rx' 

isso importará todas as coisas necessárias.