UNPKG

super-axios

Version:

一款基于axios二次封装的断线重连,防抖提交,节流请求,自动取消等功能,是一个很强大的库~

223 lines (195 loc) 6.93 kB
import axios, { AxiosInstance, AxiosPromise, AxiosRequestConfig, Method, Canceler, AxiosError, AxiosResponse } from "axios"; const cancelToken = axios.CancelToken export interface Protocol { getRequestConfig(config: AxiosRequestConfig): RequestConfig // 通过axios请求参数来获取原请求接口所有信息 reconnect<R = any>(r: RequestConfig): Promise<R | AxiosResponse<R>> // 重新请求 dispatch<R = any>(r: RequestConfig): Promise<R | AxiosResponse<R>> // 请求方法 getHashCode(r: AxiosRequestConfig): number // 获取请求唯一标识 checkRequestExists(hashCode: number): Boolean // 检测是否有存在相同请求 } export type MethodType = "default" | "delay" | "block" | "kill" export interface RequestConfig extends AxiosRequestConfig { type?: MethodType // 接口类型 reconnect?: Boolean // 是否需要重连 hashCode?: number // 当前请求hashCode delayTime?: number // 私有化延迟请求时间 cancelHandle?: Canceler // 取消请求回调方法 reconnectTimes?: number // 当前重连次数 } export interface Config extends AxiosRequestConfig { maxReconnectTimes?: number // 最大重连次数,默认为5次 delayTime?: number // 延迟毫秒数,默认为300毫秒 reconnectTime?: number // 重连时间间隔 } interface RequestUniqueObject { url: string, method: Method, } export class SuperAxios implements Protocol { public axiosInstance: AxiosInstance // axios单例对象 private queue: Map<number, RequestConfig> = new Map() // 请求队列 private readonly maxReconnectTimes: number = 5 // 最大重连次数,默认为5次 private readonly delayTime: number = 300 // 延迟毫秒数,默认为300毫秒 private Timer?: any // 延时器对象 private readonly reconnectTime: number // 重连时间间隔 constructor(config: Config) { this.axiosInstance = axios.create(config) const { maxReconnectTimes = 5, delayTime = 300, reconnectTime = 1500 } = config this.maxReconnectTimes = maxReconnectTimes this.delayTime = delayTime this.reconnectTime = reconnectTime } /*** * 重连请求 * @param r */ public reconnect<R = any>(r: RequestConfig): Promise<R | AxiosResponse<R>> { if (r.reconnectTimes! < this.maxReconnectTimes) { this.queue.delete(this.getHashCode(r)) r.reconnectTimes!++ const Reconnection = new Promise<void>((resolve) => { setTimeout(() => { resolve(); }, this.reconnectTime) }) return Reconnection.then(() => { return this.dispatch(r) }); } return Promise.reject("已经尽力了,但是网络还是不给力") } /*** * http请求最终执行方法 * @param r:RequestConfig * @return AxiosPromise<R> * @private */ dispatch<R = any>(r: RequestConfig): Promise<R | AxiosResponse<R>> { if (!r.reconnectTimes) { r.reconnectTimes = 0 } switch (r.type) { case "block": return this.block(r) case "delay": return this.delay(r) case "kill": return this.cancel(r) default: if (r.reconnect) { this.queue.set(this.getHashCode(r), r) } return this.axiosInstance(r) } } /*** * 堵塞当前请求 * @param r * @private */ private block<R = any>(r: RequestConfig): AxiosPromise<R> { const hashcode = this.getHashCode(r) if (this.checkRequestExists(hashcode)) { return Promise.reject(`在第一次未响应返回前不可重复请求该接口${r.url}`) } this.queue.set(hashcode, r) return this.resolve(r) } /*** * 续接promise动作 * @param r * @private */ private resolve<R = any>(r: RequestConfig): AxiosPromise<R> { const self = this const hashcode = self.getHashCode(r) return new Promise(((resolve, reject) => { this.axiosInstance(r).then((res) => { self.queue.delete(hashcode) resolve(res) }).catch((err: AxiosError) => { self.queue.delete(hashcode) reject(err) }) })) } /*** * 检测是否有存在相同请求 * @param hashCode * @private */ public checkRequestExists(hashCode: number): Boolean { return this.queue.has(hashCode) } /*** * 处理可取消请求 * @param r * @return RequestConfig */ private cancel<R = any>(r: RequestConfig): AxiosPromise<R> { const hashcode = this.getHashCode(r); if (this.checkRequestExists(hashcode)) { this.queue.get(hashcode)?.cancelHandle?.("取消上一次相同请求") this.queue.delete(hashcode) } this.queue.set(hashcode, r) r.cancelToken = new cancelToken(function (c: Canceler) { r.cancelHandle = c }) return this.resolve(r) } /*** * 节流请求 * @param r */ private delay<R = any>(r: RequestConfig): AxiosPromise<R> { this.Timer && clearTimeout(this.Timer) const Reconnection = new Promise<void>((resolve) => { this.Timer = setTimeout(() => { resolve(); }, r.delayTime || this.delayTime) }) return Reconnection.then(() => { return this.axiosInstance(r) }) } /*** * 通过请求参数及请求方法生成唯一标识 * @param r */ public getHashCode(r: AxiosRequestConfig): number { const {url, method} = r const obj: RequestUniqueObject = { url: <string>url, method: <Method>method, } var str = JSON.stringify(obj); var hash = 0, i, chr, len; if (str.length === 0) return hash; for (i = 0, len = str.length; i < len; i++) { chr = str.charCodeAt(i); hash = ((hash << 5) - hash) + chr; hash |= 0; // Convert to 32bit integer } return hash; } /*** * 通过AxiosRequestConfig获取RequestConfig * @param config */ public getRequestConfig(config: AxiosRequestConfig): RequestConfig { return this.queue.get(this.getHashCode(config))!; } }