您可以根据自己的需要选择一些选项。如果要根据每个请求处理错误,请在请求中添加一个catch
。如果要添加全局解决方案,请使用HttpInterceptor
。
在此处打开正在工作的演示插件,以获取以下解决方案。
tl; dr
在最简单的情况下,您只需要添加.catch()
或.subscribe()
,例如:
import 'rxjs/add/operator/catch'; // don't forget this, or you'll get a runtime error
this.httpClient
.get("data-url")
.catch((err: HttpErrorResponse) => {
// simple logging, but you can do a lot more, see below
console.error('An error occurred:', err.error);
});
// or
this.httpClient
.get("data-url")
.subscribe(
data => console.log('success', data),
error => console.log('oops', error)
);
但是,对此还有更多详细信息,请参见下文。
方法(本地)解决方案:记录错误并返回回退响应
如果只需要在一个地方处理错误,则可以使用catch
并返回默认值(或空响应),而不是完全失败。您也不需要.map
强制转换,可以使用泛型函数。来源:Angular.io-获取错误详细信息。
因此,通用.get()
方法将类似于:
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/empty';
import 'rxjs/add/operator/retry'; // don't forget the imports
@Injectable()
export class DataService {
baseUrl = 'http://localhost';
constructor(private httpClient: HttpClient) { }
// notice the <T>, making the method generic
get<T>(url, params): Observable<T> {
return this.httpClient
.get<T>(this.baseUrl + url, {params})
.retry(3) // optionally add the retry
.catch((err: HttpErrorResponse) => {
if (err.error instanceof Error) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', err.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(`Backend returned code ${err.status}, body was: ${err.error}`);
}
// ...optionally return a default fallback value so app can continue (pick one)
// which could be a default value
// return Observable.of<any>({my: "default value..."});
// or simply an empty observable
return Observable.empty<T>();
});
}
}
处理错误将使您即使在URL处的服务状况不佳时也可以继续运行应用。
当您想为每个方法返回特定的默认响应时,这种按请求的解决方案非常有用。但是,如果您只关心错误显示(或具有全局默认响应),则更好的解决方案是使用拦截器,如下所述。
在这里运行可运行的演示插件。
高级用法:拦截所有请求或响应
Angular.io指南再次显示:
@angular/common/http
拦截的主要功能是,它可以声明位于应用程序和后端之间的拦截器。当您的应用程序发出请求时,拦截器会先将其转换,然后再将其发送到服务器,并且拦截器可以在应用程序看到请求之前将响应转换回去。这对于从身份验证到日志记录的所有操作都是有用的。
当然,可以使用它以非常简单的方式来处理错误(此处为demo plunker):
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse,
HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/of';
import 'rxjs/add/observable/empty';
import 'rxjs/add/operator/retry'; // don't forget the imports
@Injectable()
export class HttpErrorInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request)
.catch((err: HttpErrorResponse) => {
if (err.error instanceof Error) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', err.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(`Backend returned code ${err.status}, body was: ${err.error}`);
}
// ...optionally return a default fallback value so app can continue (pick one)
// which could be a default value (which has to be a HttpResponse here)
// return Observable.of(new HttpResponse({body: [{name: "Default value..."}]}));
// or simply an empty observable
return Observable.empty<HttpEvent<any>>();
});
}
}
提供拦截器:只需声明HttpErrorInterceptor
以上内容,便不会导致您的应用使用它。您需要通过将其提供为拦截器,将其连接到您的应用模块中,如下所示:
import { NgModule } from '@angular/core';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpErrorInterceptor } from './path/http-error.interceptor';
@NgModule({
...
providers: [{
provide: HTTP_INTERCEPTORS,
useClass: HttpErrorInterceptor,
multi: true,
}],
...
})
export class AppModule {}
注意:如果您同时具有错误拦截器和某些本地错误处理,则很可能永远不会触发本地错误处理,因为错误将始终由拦截器处理之前到达本地错误处理处理。
在这里运行可运行的演示插件。
return this.httpClient.get<type>(...)
。然后将catch...
其实际用于服务的某个地方从服务中移出,因为那是他将建立可观察的流量并可以最好地处理它的地方。