AbortController
AbortController 是一个在现代浏览器中内置的 API,用于取消任何正在进行的请求。Axios 提供了一个 signal 选项来使用 AbortController API。
传送至官网: 取消请求 | Axios Docs (axios-http.com)
下面是如何在 Axios 请求中使用 AbortController :
javascript复制代码 const controller = new AbortController();
axios.get('/foo/bar', {
signal: controller.signal
}).then(function(response) {
//...
});
// 取消请求
controller.abort();
通过使用 AbortController 的实例,我们可以在需要时调用 abort() 方法来取消请求。
在 Axios 中,我们可以将 AbortController 与 AxiosRequestConfig 的 signal 选项一起使用。
具体来说,我们可以为每个请求创建一个 AbortController 实例,并将其添加到请求配置中,以便我们可以随时取消请求。
封装 AbortController 的示例:
import type {AxiosRequestConfig } from 'axios'
//等待中的所有请求
const pendingMap=new Map<string,AbortController>()
function getPendingUrl(config:AxiosRequestConfig){
return [config.method,config.url].join('&')
}
export class AxiosCancel{
/**
* @description: 添加请求
* @return {*}
*/
public addPending(config:AxiosRequestConfig){
const url=getPendingUrl(config)
const controller=new AbortController()
config.signal=controller.signal
if(!pendingMap.has(url)){
pendingMap.set(url,controller)
}
console.log(pendingMap);
}
/**
* @description: 清除请求
* @return {*}
*/
public removePending(config:AxiosRequestConfig){
const url=getPendingUrl(config)
if(pendingMap.has(url)){
const controller=pendingMap.get(url)
if(controller){
console.log('请求取消');
controller.abort()
}
//缓存列表清除
pendingMap.delete(url)
}
}
/**
* @description: 终止一切pending请求
* @return {*}
*/
public removeAllPending(){
pendingMap.forEach((item)=>{
if(item){
item.abort()
}
})
pendingMap.clear()
}
}
以上提供的代码实现了一个基本的AxiosCanceler类。这个类可以用来取消正在进行的请求。在这个类中,我们创建了一个pendingMap对象,它用于存储每个请求的标识和取消函数。当请求被发出时,我们将其添加到pendingMap中。如果需要取消请求,我们可以使用AbortController.abort()方法取消请求。
在AxiosCanceler类中,我们定义了addPending、removeAllPending和removePending三个方法。addPending方法用于发送请求时,将其添加到pendingMap中。removeAllPending方法可以用于取消所有处于pending的请求,而removePending方法可以用于取消单个请求。
使用AbortCancel封装类实例
import axios from "axios";
import {AxiosCancel} from './AbortController'
import type { AxiosRequestConfig } from "axios";
export function reqTest(){
let reqConfig:AxiosRequestConfig={method:'post',url:'/api/test'}
//每次发送请求前,先取消缓存列表中的请求,然后重新添加
cancel.removePending(reqConfig)
cancel.addPending(reqConfig)
return request<any,any>(reqConfig)
}
总结
如果你在你的应用程序中需要管理多个请求,并且需要在请求发出后取消这些请求,那么AxiosCanceler类将是一个非常有用的工具。它可以让你更好地控制你的异步请求,并避免一些不必要的错误。
二次封装的axios
//index.ts
import axios from 'axios'
import type {
AxiosInstance,
InternalAxiosRequestConfig,
AxiosResponse,
} from 'axios'
import type { RequestConfig } from './type'
class Request {
instance: AxiosInstance
constructor(config: RequestConfig) {
this.instance = axios.create(config)
this.instance.interceptors.request.use(
(config: InternalAxiosRequestConfig) => {
return config
},
(err) => {
console.log(err)
}
)
this.instance.interceptors.response.use(
(res: AxiosResponse) => {
return res
},
(err) => {
console.log(err)
}
)
/* 实例拦截器 */
if (config.interceptors) {
this.instance.interceptors.request.use(
config.interceptors?.requestInterceptors,
config.interceptors?.requestInterceptorsCatch
)
this.instance.interceptors.response.use(
config.interceptors?.responseInterceptors,
config.interceptors.responseInterceptorsCatch
)
}
}
/*
二次封装请求方法
*/
request<T>(config: RequestConfig) {
//如果请求方法里额外传递了拦截器,那么就调用,它反正还会返回对应的config的
return new Promise<T>((resolve, reject) => {
if (config.interceptors?.requestInterceptors) {
config = config.interceptors.requestInterceptors(config)
}
//调用axios自带的request方法,最后需要resolve(T类型的值)
this.instance.request<any, T>(config).then(
(res) => {
if (config.interceptors?.responseInterceptors) {
res = config.interceptors?.responseInterceptors(res)
}
resolve(res)
},
(err) => {
reject(err)
}
)
})
}
}
export default Request
//type.ts
import type {
AxiosRequestConfig,
InternalAxiosRequestConfig,
AxiosResponse,
} from 'axios'
type instanceInterceptors = {
requestInterceptors?: (
config: InternalAxiosRequestConfig | AxiosRequestConfig
) => InternalAxiosRequestConfig
requestInterceptorsCatch?: (err: any) => void
responseInterceptors?: <T = AxiosResponse>(res: T) => T
responseInterceptorsCatch?: (err: any) => any
}
export interface RequestConfig extends AxiosRequestConfig {
interceptors?: instanceInterceptors
}
使用
//单个实例封装的拦截器
import Request from './index'
const baseRequest = new Request({
baseURL: 'http://localhost:8080/api',
timeout: 5000,
interceptors: {
responseInterceptors(res) {
return res.data
},
},
})
export default baseRequest.instance
//单个请求封装拦截器
mport Request from './index'
const baseRequest = new Request({
baseURL: 'http://localhost:8080/api',
timeout: 5000,
})
export default baseRequest
//请求文件
import request from '../baseRequest'
type form = {
name: string
data: any
}
export const getLogin = () => {
return request.request<form>({
url: '/get',
interceptors: {
responseInterceptors(res) {
return res
},
},
})
}