新服务已更新为使用HttpClientModule和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) {
console.log(`status: ${err.status}, ${err.statusText}`);
}
return Observable.throw(errMsg);
}
}
public getData() : Observable<SomeClassOrInterface> {
return this._http.get<SomeClassOrInterface>(this.url)
.pipe(
tap(data => console.log('server data:', data)),
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/add/operator/map';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';
@Injectable()
export class MyService {
constructor(private _http:Http) {}
private _serverError(err: any) {
console.log('sever error:', err);
if(err instanceof Response) {
return Observable.throw(err.json().error || 'backend server error');
}
return Observable.throw(err || 'backend server error');
}
private _request = new Request({
method: "GET",
url: "./data/data.json"
});
public getData() {
return this._http.request(this._request)
.map(res => res.json())
.do(data => console.log('server data:', data))
.catch(this._serverError);
}
}
我使用.do()
(现在使用的是.tap()
)进行调试。
当服务器出现错误时,我从使用的服务器(lite-server)获取的Response
对象的body
仅包含文本,因此我使用err.text()
而不是err.json().error
。您可能需要根据您的服务器调整该行代码。
如果res.json()
引发错误,因为它无法解析JSON数据,则_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
);
}
}
throw()
函数的同样问题。我改为添加这一行代码import 'rxjs/Rx';
。现在所有的操作符都正常工作了。 - Nick.catch
是否真的起作用了吗?那个.subscribe()
肯定是有效的。 - acdcjuniorEXCEPTION: TypeError: Observable_1.Observable.throw is not a function
。可以通过 @MattScarpino 的答案或者我之前提到的这个 plunker 中的方法来解决:https://angular.io/resources/live-examples/server-communication/ts/plnkr.html - Nickthrow
即可:import 'rxjs/add/observable/throw';
,不要导入全部内容,因为太庞大了。 - dfsq