赞
踩

这两个功能都是用拦截器实现。
前景提要:
ts 简易封装 axios,统一 API
实现在 config 中配置开关拦截器
在构造函数中,添加一个响应拦截器即可。在构造函数中注册拦截器的好处是,无论怎么实例化封装类,这个错误拦截器都会被注册进实例。
其中有个注意点,就是请求取消。取消请求会导致响应 promise 状态为 rejected,这样就会触发响应拦截器的 onRejected 回调。因此要单独处理请求的请求情况,将它与请求错误区分开来。
class HttpRequest { private readonly instance: AxiosInstance; constructor(config: MyAxiosRequestConfig) { this.instance = axios.create(config); // axios http 错误处理(超出 2xx 范围的 http 状态码都会触发该函数) this.instance.interceptors.response.use(null, (error: AxiosError) => { // 手动取消请求会导致“错误”触发 if (error.message === "canceled") alert("请求取消成功"); const { response } = error; // 1. 请求超时 && 网络错误单独判断,因为没有 response if (error.message.indexOf("timeout") !== -1) alert("请求超时!请您稍后重试"); if (error.message.indexOf("Network Error") !== -1) alert("网络错误!请您稍后重试"); // 2. 根据 http 服务器响应的错误状态码,做不同的处理 if (response) { switch (response.status) { case 404: alert("你所访问的资源不存在!"); break; case 500: alert("服务异常!"); break; default: alert("请求失败!"); } } // 3. 服务器结果都没有返回(可能服务器错误可能客户端断网),断网处理:也可以跳转到断网页面 if (!window.navigator.onLine) alert("服务器错误或者无网络"); // router.replace("/500"); throw error; }); } }
axios 取消请求有两种 api。一种是 AbortController,一种是古老的 CancelToken ,已经被弃用了。
AbortController - Web API 接口参考 | MDN
我们主要使用第一种方式:
signalsignal配置abort()方法就能取消被标记了的请求。const controller = new AbortController();
axios.get('/foo/bar', {
signal: controller.signal
}).then(function(response) {
//...
});
// 取消请求
controller.abort()
取消请求也是个基础功能,因此和全局错误拦截器一样在构造函数中注册拦截器。
取消请求:
封装类暴露两个方法:
class HttpRequest { private readonly instance: AxiosInstance; private readonly abortControllerMap: Map<string, AbortController>; constructor(config: MyAxiosRequestConfig) { this.instance = axios.create(config); // 为每个请求都生成一个 signal,并以 url 为 key 添加入 map this.instance.interceptors.request.use( config => { // 如果具体方法中设置了 signal,这里就不再添加,避免覆盖。 if (config.signal) return config; const controller = new AbortController(); config.signal = controller.signal; const url = config.url || ""; this.abortControllerMap.set(url, controller); return config; }, (err: AxiosError) => { throw err; } ); // 响应完,从map中去除 url this.instance.interceptors.response.use( res => { const url = res?.config.url || ""; this.abortControllerMap.delete(url); return res; }, (err: AxiosError) => { const url = err?.config?.url || ""; this.abortControllerMap.delete(url); throw err; } ); } /** * 取消全部请求 */ cancelAllRequest() { for (const [, controller] of this.abortControllerMap) { controller.abort(); } this.abortControllerMap.clear(); } /** * 取消指定的请求 * (并发上传文件的url通常是一样的,通过url取消请求会取消所有上传操作,故此方法不宜用来取消上传请求) * @param url 待取消的请求URL */ cancelRequest(url: string | string[]) { const urlList = Array.isArray(url) ? url : [url]; urlList.forEach(_url => { this.abortControllerMap.get(_url)?.abort(); this.abortControllerMap.delete(_url); }); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。