背景需求:
- 1.项目开发、测试、发布使用的后台发布接口均不一致,根据不同环境配置接口的host+port
- 2.全局处理非正确的response
- 3.每次请求前显示loading,请求后隐藏loading(本文不涉及)
实现:
-
1.自定义HttpInterceptorService(http.interceptor.service.ts)
import { Injectable } from '@angular/core'; import { Http, Request, RequestOptionsArgs, Response, RequestOptions, ConnectionBackend, Headers } from '@angular/http'; import 'rxjs/Rx'; import { Observable } from 'rxjs/Observable'; @Injectable() export class HttpInterceptorService extends Http { status = { "status.400": "错误的请求。由于语法错误,该请求无法完成。", "status.401": "未经授权。服务器拒绝响应。", "status.403": "已禁止。服务器拒绝响应。", "status.404": "未找到。无法找到请求的位置。", "status.405": "方法不被允许。使用该位置不支持的请求方法进行了请求。", "status.406": "不可接受。服务器只生成客户端不接受的响应。", "status.407": "需要代理身份验证。客户端必须先使用代理对自身进行身份验证。", "status.408": "请求超时。等待请求的服务器超时。", "status.409": "冲突。由于请求中的冲突,无法完成该请求。", "status.410": "过期。请求页不再可用。", "status.411": "长度必需。未定义“内容长度”。", "status.412": "前提条件不满足。请求中给定的前提条件由服务器评估为 false。", "status.413": "请求实体太大。服务器不会接受请求,因为请求实体太大。", "status.414": "请求 URI 太长。服务器不会接受该请求,因为 URL 太长。", "status.415": "不支持的媒体类型。服务器不会接受该请求,因为媒体类型不受支持。", "status.416": "HTTP 状态代码 {0}", "status.500": "内部服务器错误。", "status.501": "未实现。服务器不识别该请求方法,或者服务器没有能力完成请求。", "status.503": "服务不可用。服务器当前不可用(过载或故障)。" }; constructor(backend: ConnectionBackend, defaultOptions: RequestOptions) { super(backend, defaultOptions); } request(url: string | Request, options ? : RequestOptionsArgs): Observable < Response > { //console.log("before..."); //根据不同的生产环境配置http前缀 typeof url=='string'? (url='http://192.168.1.205:8099/'+url):(url.url='http://192.168.1.205:8099/'+url.url); return this.intercept(super.request(url, options)); } get(url: string, options ? : RequestOptionsArgs): Observable < Response > { return this.intercept(super.get(url, options)); } post(url: string, body: string, options ? : RequestOptionsArgs): Observable < Response > { return this.intercept(super.post(url, body, this.getRequestOptionArgs(options))); } put(url: string, body: string, options ? : RequestOptionsArgs): Observable < Response > { return this.intercept(super.put(url, body, this.getRequestOptionArgs(options))); } delete(url: string, options ? : RequestOptionsArgs): Observable < Response > { return this.intercept(super.put(url, this.getRequestOptionArgs(options))); } getRequestOptionArgs(options ? : RequestOptionsArgs): RequestOptionsArgs { if (options == null) { options = new RequestOptions(); } if (options.headers == null) { options.headers = new Headers(); } options.headers.append('Content-Type', 'application/json'); return options; } intercept(observable: Observable < Response > ): Observable < Response > { //console.log("after..."); return observable.catch((err, source) => { if (err.status<200 || err.status>=300) { alert('网络错误:'+err.status+' - '+this.status['status.'+err.status]); return Observable.empty(); } else { return Observable.throw(err); } }); } }
-
2.在app.module.ts中provide
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { Http, HttpModule, XHRBackend, RequestOptions } from '@angular/http'; import { RouterModule, Routes } from '@angular/router'; import { MessagesModule, GrowlModule, ConfirmDialogModule, ConfirmationService, DialogModule, BlockUIModule } from 'primeng/primeng'; import { AppComponent } from './app.component'; import { HttpInterceptorService } from './shared/http.interceptor.service'; export function interceptorFactory(xhrBackend: XHRBackend, requestOptions: RequestOptions){ let service = new HttpInterceptorService(xhrBackend, requestOptions); return service; } @NgModule({ imports: [ BrowserModule, FormsModule, HttpModule, RouterModule.forRoot(appRoutes), LoginModule, FrameModule, MessagesModule, GrowlModule, ConfirmDialogModule, DialogModule, BlockUIModule ], declarations: [ AppComponent ], bootstrap: [ AppComponent ], providers: [ HttpInterceptorService, { provide: Http, useFactory: interceptorFactory, deps: [XHRBackend, RequestOptions] } ] }) export class AppModule { }
-
3.使用,示例:app.component.ts
import { Component } from '@angular/core'; import { Http } from '@angular/http'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { title = 'app works!'; constructor(private http: Http){} ngOnInit(){ this.http.get('api/user/functions') .toPromise() .then(res => console.log(res)); } }