import Axios, { AxiosInstance, AxiosResponse, AxiosRequestConfig, Canceler } from 'axios'; import { RequestType } from './index.type'; class Request implements RequestType { public instance: AxiosInstance; private theQueue: { info: string; c: Canceler; }[] = []; constructor(config: AxiosRequestConfig) { this.instance = this.genInstance(config); this.interceptorsRequest(); this.interceptorsResponse(); } async request(config: AxiosRequestConfig) { return await this.instance.request(config); } private genInstance(config: AxiosRequestConfig) { return Axios.create({ timeout: 1000 * 10, ...config, }); } // 添加请求拦截器 private interceptorsRequest() { this.instance.interceptors.request.use( (config: any) => { config.cancelToken = new Axios.CancelToken((c) => { this.findInQueue({ info: `${config.url}_${config.method}`, c, }); // 类似这种取消请求 // 其实服务端是有收到的 // 只是浏览器层面做了一层处理 }); return config; }, function (error) { // 对请求错误做些什么 return Promise.reject(error); }, ); } // 添加响应拦截器 private interceptorsResponse() { this.instance.interceptors.response.use( (response: AxiosResponse) => { const config = response.config; this.removeQueue({ info: `${config.url}_${config.method}`, }); // 格式化响应数据 return Promise.resolve({ ...response, code: 0, message: 'success', }); }, (error) => { // 遗留问题: 超时时拿不到响应对象,就无法删除 theQueue 队列 const config = (error.response && error.response.config) || {}; this.removeQueue({ info: `${config.url}_${config.method}`, }); const { data } = error.response || {}; return Promise.reject({ ...error.response, code: -1, message: data?.error_description || error.message, }); }, ); } private findInQueue(requestInfo: any) { const index = this.theQueue.findIndex((request) => request.info === requestInfo.info); if (index >= 0) { this.theQueue[index].c('取消请求'); this.theQueue.splice(index, 1); } this.theQueue.push(requestInfo); } private removeQueue(requestInfo: any) { const index = this.theQueue.findIndex((request) => request.info === requestInfo.info); if (index < 0) return; this.theQueue.splice(index, 1); } } export default Request;