众所周知,angular4以后引入的HTTPClient为前端http请求带来了非常大的改进,它支持了与java类似的拦截器机制,通过拦截器,可以方便的对请求进行前置、后置及异常处理。但如果我们需要在不同的项目中使用这个拦截器,且有不同的业务处理逻辑该怎么办呢?
编写这个组件是为了提供一个简便的请求方法
ionic g provider http
在providers/http文件夹下新增一个文件RequestMethods.ts用来存放支持的请求类型,内容如下:
export enum RequestMethods {
GET = 'GET',
POST = 'POST',
DELETE = 'DELETE',
OPTIONS = 'OPTIONS',
PATCH = 'PATCH',
TRACE = 'TRACE',
HEAD = 'HEAD'
}
import {HttpClient} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {Observable} from "rxjs";
import {RequestMethods} from "./RequestMethods";
import {Logger} from "../../common/logger/logger";
@Injectable()
export class HttpProvider {
constructor(private httpClient: HttpClient, private logger: Logger) {
logger.log("HttpProvider Init OK");
}
/**
* 发起一个get请求
* @param url
* @param paramMap
* @param header
*/
get(url: string, paramMap: {} = {}, header: {} = {}): Observable
ionic g provider interceptor
新增如下图所示的几个组件,组建的作用后面在说:
包括:
DefaultRequestExceptionHandler.ts
DefaultRequestPreviewHandler.ts
DefaultRequestProcessedHandler.ts
RequestExceptionHandler.ts
RequestPreviewHandler.ts
RequestProcessedHandler.ts
import {
HttpClient,
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest,
HttpResponse
} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {Logger} from "../../../common/logger/logger";
import {catchError, tap} from "rxjs/operators";
import {Observable} from "rxjs";
import {RequestProcessedHandler} from "../handler/RequestProcessedHandler";
import {RequestPreviewHandler} from "../handler/RequestPreviewHandler";
import {RequestExceptionHandler} from "../handler/RequestExceptionHandler";
import {Constants} from "../../../common/Constants";
@Injectable()
export class LarkHttpInterceptor implements HttpInterceptor {
private timeoutMillis;
constructor(public http: HttpClient,
public logger: Logger,
private requestProcessedHandler: RequestProcessedHandler,
private requestPreviewHandler: RequestPreviewHandler,
private requestExceptionHandler: RequestExceptionHandler) {
logger.log('Hello InterceptorProvider Provider');
this.timeoutMillis = Constants.TIMEOUT_MILLS || 3000;
}
intercept(request: HttpRequest, next: HttpHandler): Observable> {
/**
* 请求前置处理
*/
this.requestPreviewHandler.handle(request);
return next.handle(request).timeout(this.timeoutMillis)
.pipe(
tap(event => {
if (event instanceof HttpResponse) {
/**
* 请求后置处理
*/
this.requestProcessedHandler.handle(event);
}
}, error => {
/**
* 请求异常处理
*/
this.requestExceptionHandler.handle(error);
}),
catchError((err: any) => {
this.requestExceptionHandler.handle(err);
return Observable.throw(err.message);
})
)
};
}
RequestExceptionHandler(请求异常处理器类):
import {Injectable} from "@angular/core";
@Injectable()
export class RequestExceptionHandler {
handle(request: any): any {
return request;
};
}
RequestPreviewHandler(请求前置处理器类):
import {HttpRequest} from "@angular/common/http";
import {Injectable} from "@angular/core";
@Injectable()
export class RequestPreviewHandler {
handle(request: HttpRequest): HttpRequest {
return request;
};
}
RequestProcessedHandler(请求后置处理器类):
import {HttpResponse} from "@angular/common/http";
import {Injectable} from "@angular/core";
@Injectable()
export class RequestProcessedHandler {
handle(req: HttpResponse): any {
return undefined;
};
}
DefaultRequestExceptionHandler(默认请求异常处理器实现类):
import {Injectable} from "@angular/core";
import {HttpResponse} from "@angular/common/http";
import {Logger} from "../../../../common/logger/logger";
import {RequestExceptionHandler} from "../RequestExceptionHandler";
import {TimeoutError} from "rxjs";
@Injectable()
export class DefaultRequestExceptionHandler extends RequestExceptionHandler {
constructor(private logger: Logger) {
super();
}
handle(res: any): any {
this.logger.warn("未注入自定义请求异常处理类,使用默认异常处理");
if (res instanceof HttpResponse) {
switch (res.status) {
case 200:
this.logger.log("业务异常")
break;
case 404:
this.logger.log("请求失败,未找到请求地址!");
case 500:
this.logger.log("请求失败,服务器出错,请稍后再试!");
case 0:
this.logger.log("请求失败,请求响应出错!");
default:
this.logger.log(res);
}
} else {
if(res instanceof TimeoutError){
this.logger.log("请求失败,超时TimeOut!");
}
this.logger.log(res);
}
return res;
}
}
DefaultRequestPreviewHandler(默认请求前置处理器实现类):
import {Injectable} from "@angular/core";
import {RequestPreviewHandler} from "../RequestPreviewHandler";
import {HttpRequest} from "@angular/common/http";
import {Logger} from "../../../../common/logger/logger";
@Injectable()
export class DefaultRequestPreviewHandler extends RequestPreviewHandler {
constructor(private logger: Logger) {
super();
}
handle(request: HttpRequest): HttpRequest {
this.logger.warn("未注入自定义请求前置处理类,使用默认前置处理");
return request;
}
}
DefaultRequestProcessedHandler(默认请求后置处理器实现类):
import {HttpResponse} from "@angular/common/http";
import {Logger} from "../../../../common/logger/logger";
import {RequestProcessedHandler} from "../RequestProcessedHandler";
import {Injectable} from "@angular/core";
@Injectable()
export class DefaultRequestProcessedHandler extends RequestProcessedHandler {
constructor(private logger: Logger) {
super();
}
handle(req: HttpResponse): any {
this.logger.warn("未注入自定义请求后置处理类,使用默认后置处理");
this.logger.log(req);
return req.body;
}
}
4.在app.module.ts中配置注入
import {DefaultRequestProcessedHandler} from "../providers/http/handler/default-handler/DefaultRequestProcessedHandler";
import {LarkHttpInterceptor} from "../providers/http/interceptor/interceptor";
import {RequestProcessedHandler} from "../providers/http/handler/RequestProcessedHandler";
import {RequestPreviewHandler} from "../providers/http/handler/RequestPreviewHandler";
import {DefaultRequestPreviewHandler} from "../providers/http/handler/default-handler/DefaultRequestPreviewHandler";
import {RequestExceptionHandler} from "../providers/http/handler/RequestExceptionHandler";
import {DefaultRequestExceptionHandler} from "../providers/http/handler/default-handler/DefaultRequestExceptionHandler";
......
providers: [
StatusBar,
SplashScreen,
{provide: RequestPreviewHandler, useClass: DefaultRequestPreviewHandler},
{provide: RequestProcessedHandler, useClass: DefaultRequestProcessedHandler},
{provide: RequestExceptionHandler, useClass: DefaultRequestExceptionHandler},
{provide: HTTP_INTERCEPTORS, useClass: LarkHttpInterceptor, multi: true},
HttpProvider,
]
constructor(public navCtrl: NavController, public http: HttpProvider, public logger: Logger) {
this.http.get("https://www.sojson.com/api/qqmusic/8446666/json").subscribe(
(info) => {
this.logger.log("请求成功", info);
}
)
}
通过暴露三个可供继承重写的处理器类,可非常的在不同的场景下修改请求前后及异常时的处理逻辑,实现了公共组件与业务的解耦,方便了配置。