如何从http.request()正确捕获exception?
我的部分代码:
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()
在浏览器的控制台中产生exception:
ORIGINAL EXCEPTION:TypeError:this.http.request(…)。map(…)。catch不是一个函数
也许你可以尝试在你的导入中添加这个:
import 'rxjs/add/operator/catch';
你也可以这样做:
return this.http.request(request) .map(res => res.json()) .subscribe( data => console.log(data), err => console.log(err), () => console.log('yay') );
每个评论:
例外:TypeError:Observable_1.Observable.throw不是一个函数
同样,为此,您可以使用:
import 'rxjs/add/observable/throw';
新服务更新为使用HttpClientModule:
import { Injectable } from '@angular/core'; import { HttpClient, HttpErrorResponse } from '@angular/common/http'; import { Observable } from 'rxjs/Observable'; import { catchError } from 'rxjs/operators'; import { SomeTypeOrInterface } 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<SomeTypeOrInterface> { // HttpClient.get() returns the body of the response as an untyped JSON object. // We specify the type as SomeTypeOrInterface to get a typed result. return this._http.get<SomeTypeOrInterface>(this.assetUrl) .pipe( catchError(this.handleError('getData')) ); }
旧服务,它使用不推荐的HttpModule:
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); } }
我使用.do()
进行debugging。
当出现服务器错误时,从我使用的服务器(lite-server)获取的Response
对象body
仅包含文本,因此我使用上面的err.text()
而不是err.json().error
。 您可能需要为您的服务器调整该行。
如果res.json()
由于无法parsingJSON数据而引发错误, _serverError
将不会得到一个Response
对象,因此是检查instanceof
的原因。
在这个plunker中 ,将url
更改为./data/data.junk
以生成错误。
任一服务的用户都应该有可以处理错误的代码:
@Component({ selector: 'my-app', template: '<div>{{data}}</div> <div>{{errorMsg}}</div>` }) export class AppComponent { errorMsg: string; constructor(private _myService: MyService ) {} ngOnInit() { this._myService.getData() .subscribe( data => this.data = data, err => this.errorMsg = <any>err ); } }
在最新版本的angular4中使用
import { Observable } from 'rxjs/Rx'
它会导入所有需要的东西。
RxJSfunction需要专门导入。 一个简单的方法是将import * as Rx from "rxjs/Rx"
所有functionimport * as Rx from "rxjs/Rx"
然后确保以Rx.Observable
访问Observable
类。