Come rilevare correttamente l’eccezione da http.request ()?

Parte del mio codice:

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 un’eccezione nella console del browser:

ECCEZIONE ORIGINALE: TypeError: this.http.request (…). Map (…). Catch non è una funzione

Forse puoi provare ad aggiungerlo nelle tue importazioni:

 import 'rxjs/add/operator/catch'; 

Puoi anche fare:

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

Per commenti:

ECCEZIONE: TypeError: Observable_1.Observable.throw non è una funzione

Allo stesso modo, per questo, puoi usare:

 import 'rxjs/add/observable/throw'; 

Nuovo servizio aggiornato per utilizzare HttpClientModule e 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')) ); } 

Vecchio servizio, che utilizza il HttpModule deprecato:

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

Io uso .do() ( ora .tap() ) per il debug.

Quando c’è un errore del server, il body dell’object Response che ottengo dal server che sto usando (lite-server) contiene solo testo, da qui il motivo per cui uso err.text() sopra piuttosto che err.json().error Potrebbe essere necessario regolare quella linea per il tuo server.

Se res.json() genera un errore perché non è in grado di analizzare i dati JSON, _serverError non otterrà un object Response , quindi il motivo per il controllo instanceof .

In questo plunker , cambia l’ url in ./data/data.junk per generare un errore.


Gli utenti di entrambi i servizi devono avere codice in grado di gestire l’errore:

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

Le funzioni RxJS devono essere importate in modo specifico. Un modo semplice per farlo è importare tutte le sue funzionalità con import * as Rx from "rxjs/Rx"

Quindi assicurati di accedere alla class Observable come Rx.Observable .

nell’ultima versione di angular4 use

 import { Observable } from 'rxjs/Rx' 

importerà tutte le cose richieste.