1、修改index.ts文件

添加请求拦截器响应拦截器代码:

  1. // src/index.ts
  2. axios.interceptors.request.use(
  3. (config: AxiosRequestConfig): AxiosRequestConfig => {
  4. console.log("请求拦截器1");
  5. return config;
  6. }
  7. );
  8. axios.interceptors.response.use((response: AxiosResponse) => {
  9. if (response.status === 200) {
  10. console.log("响应拦截器1")
  11. response.data.message += "1";
  12. }
  13. return response;
  14. });

2、修改types.ts文件

添加interceptors对象类型:

  1. // src/axios/types
  2. export interface AxiosInstance {
  3. <T = any>(config: AxiosRequestConfig): Promise<AxiosResponse<T>>;
  4. interceptors:{
  5. request: AxiosInterceptorManager<AxiosRequestConfig>;
  6. response: AxiosInterceptorManager<AxiosResponse>;
  7. }
  8. }

3、添加AxiosInterceptorManager.ts文件

image.png

  1. // src/axios/AxiosInterceptorManager.ts
  2. interface OnFulfilled<V> {
  3. (value: V): V | Promise<V>;
  4. }
  5. interface OnRejected {
  6. (error: any): any;
  7. }
  8. // 某一个拦截器
  9. export interface Interceptor<V> {
  10. // 成功回调
  11. onFulfilled?: OnFulfilled<V>;
  12. // 失败的回调
  13. onRejected?: OnRejected;
  14. }
  15. // V可能是AxiosRequestConfig,也可能是AxiosResponse
  16. export default class AxiosInterceptorManager<V> {
  17. public interceptors: Array<Interceptor<V> | null> = [];
  18. // 返回值为索引
  19. use(onFulfilled?: OnFulfilled<V>, onRejected?: OnRejected): number {
  20. this.interceptors.push({
  21. onFulfilled,
  22. onRejected,
  23. });
  24. return this.interceptors.length - 1;
  25. }
  26. eject(id:number) {
  27. if(this.interceptors[id]){
  28. this.interceptors[id] = null
  29. }
  30. }
  31. }

4、修改Axios.ts文件

添加拦截器,修改request方法:

  1. // src/axios/Axios.ts
  2. import { AxiosRequestConfig, AxiosResponse } from "./types";
  3. import AxiosInterceptorManager, {
  4. Interceptor,
  5. } from "./AxiosInterceptorManager";
  6. import qs from "qs";
  7. import parseHeaders from "parse-headers";
  8. export default class Axios<T> {
  9. public interceptors = {
  10. request: new AxiosInterceptorManager<AxiosRequestConfig>(),
  11. response: new AxiosInterceptorManager<AxiosResponse<T>>(),
  12. };
  13. // T用来限制相应对象response里的data的类型
  14. request(config: AxiosRequestConfig): Promise<AxiosResponse<T> | AxiosRequestConfig> {
  15. const chain: Array<
  16. Interceptor<AxiosRequestConfig> | Interceptor<AxiosResponse<T>>
  17. > = [
  18. {
  19. // 请求
  20. onFulfilled: this.dispatchRequest,
  21. // onRejected可以省略
  22. onRejected: (error: any) => error,
  23. },
  24. ];
  25. // 请求拦截器倒序
  26. this.interceptors.request.interceptors.forEach(
  27. (interceptor: Interceptor<AxiosRequestConfig> | null) => {
  28. interceptor && chain.unshift(interceptor);
  29. }
  30. );
  31. // 响应拦截器正序
  32. this.interceptors.response.interceptors.forEach(
  33. (interceptor: Interceptor<AxiosResponse<T>> | null) => {
  34. interceptor && chain.push(interceptor);
  35. }
  36. );
  37. let promise: any = Promise.resolve(config);
  38. while (chain.length) {
  39. const { onFulfilled, onRejected } = chain.shift()!;
  40. promise = promise.then(onFulfilled, onRejected);
  41. }
  42. return promise
  43. }
  44. // 定义一个开发请求的方法
  45. dispatchRequest<T>(config: AxiosRequestConfig): Promise<AxiosResponse<T> | AxiosRequestConfig> {
  46. return new Promise<AxiosResponse<T>>(function (resolve, reject) {
  47. let { method, url, params, headers, data, timeout } = config;
  48. let request = new XMLHttpRequest();
  49. // {name:'admin',password:'123'}转成?name=admin&password=123
  50. if ((params && method === "get") || method === "GET") {
  51. params = qs.stringify(params);
  52. // 判断url有无参数
  53. url += (url!.indexOf("?") === -1 ? "?" : "&") + params;
  54. }
  55. request.open(method!, url!, true);
  56. // 返回json类型
  57. request.responseType = "json";
  58. request.onreadystatechange = function () {
  59. if (request.readyState === 4 && request.status !== 0) {
  60. if (request.status >= 200 && request.status < 300) {
  61. let response: AxiosResponse<T> = {
  62. data: request.response ? request.response : request.responseText,
  63. status: request.status,
  64. statusText: request.statusText,
  65. headers: parseHeaders(request.getAllResponseHeaders()),
  66. config,
  67. request,
  68. };
  69. resolve(response);
  70. } else {
  71. // 错误状态码处理
  72. reject(`error:request failed with status code ${request.status}`);
  73. }
  74. }
  75. };
  76. // 处理header
  77. if (headers) {
  78. for (let key in headers) {
  79. request.setRequestHeader(key, headers[key]);
  80. }
  81. }
  82. // 处理data
  83. let body: string | null = null;
  84. if (data) {
  85. body = JSON.stringify(data);
  86. }
  87. // 网络错误处理
  88. request.onerror = function () {
  89. reject("net:error");
  90. };
  91. // 超时设置错误
  92. if (timeout) {
  93. request.timeout = timeout;
  94. request.ontimeout = function () {
  95. reject(`err:timeout of ${timeout}ms exceeded`);
  96. };
  97. }
  98. request.send(body);
  99. });
  100. }
  101. }

5、实现效果

image.png

6、源代码

代码地址:https://gitee.com/linhexs/handwritten-axios/tree/3.interceptors/