AbortController
AbortController
接口表示一个控制器对象,允许你根据需要中止一个或多个 Web 请求。
你可以使用 AbortController.AbortController()
构造函数创建一个新的 AbortController
。使用 AbortSignal
对象可以完成与 DOM 请求的通信。
示例
发送请求
export const getConsumableByPage = (data,config) => get('/Consumable/findByPage', data,config) // 获取列表
const getList = () => {
controller = new AbortController();
const signal = controller.signal;
getConsumableByPage(searchParams, { signal }).then(res => {
loading.close()
if (res.code === 200) {
tableOptions.list = res.data?.content
searchParams.total = res.data?.totalElements
}
}).catch(err => {
console.log(err)
loading.close()
})
}
中断请求
const terminateRequest= ()=>{
if (controller) {
controller.abort();
console.log("中止请求");
}
}
request 封装
1、定义变量
const {isCancel} = axios
const cacheRequest = {}
2 定义终止函数
/**
* 终止请求
* @param {*} resKey
*/
const removeCacheRequest=(resKey)=>{
if(cacheRequest[resKey]){
cacheRequest[resKey].abort();
delete cacheRequest[resKey]
}
}
3、请求拦截器里处理终止请求操作
request.interceptors.request.use(
config => {
const {url,method,removeCache=false} = config
if(removeCache){// 终止请求
removeCacheRequest(`${url}&${method}`)// 如果请求函数里传了需要清除重复请求的removeCache,并且这个重复请求存在,删除之前的请求
const controller = new AbortController();
config.signal = controller.signal;
cacheRequest[`${url}&${method}`] = controller
}
return config
},
error => {
return Promise.reject(error)
}
)
4、在响应拦截器里处理终止请求
request.interceptors.response.use(
response => {
// 请求成功,从队列里删除该controller
const {url,method,removeCache=false} = response.config
if(removeCache) removeCacheRequest(`${url}&${method}`)
},
error => {
let code = 0
try {
code = error.response.data.status
} catch (e) {
}
if(isCancel(error)){
return Promise.reject({
msg:'重复请求,自动拦截并取消'
})
}else{
return Promise.reject(error)
}
}
)
5、应用举例
export const getConsumableByPage = (data) => get('/Consumable/findByPage', data,{removeCache:true})
request 封装全代码
import axios from 'axios'
import { apiPath, loginInterception } from '@/config' // 线上服务
const {isCancel} = axios
const cacheRequest = {}
// import store from '@/store'
import router from '@/router'
import { pinia, userStore } from '@/store'
import { ElMessage } from 'element-plus'
const store = userStore(pinia)
/**
* 终止请求
* @param {*} resKey
*/
const removeCacheRequest=(resKey)=>{
if(cacheRequest[resKey]){
cacheRequest[resKey].abort();
delete cacheRequest[resKey]
}
}
const request = axios.create({
baseURL: apiPath,
timeout: 50 * 1000
})
request.interceptors.request.use(
config => {
// console.log(store)
const {url,method,removeCache=false} = config
console.log('请求拦截器',url,method,removeCache)
const token = store.token
const tenantId = store.tenant_id
if (token) {
config.headers.token = token
}
if (tenantId) {
config.headers['x-tenant-id'] = tenantId
}
if(removeCache){// 终止请求
removeCacheRequest(`${url}&${method}`)// 如果请求函数里传了需要清除重复请求的removeCache,并且这个重复请求存在,删除之前的请求
const controller = new AbortController();
config.signal = controller.signal;
cacheRequest[`${url}&${method}`] = controller
}
return config
},
error => {
return Promise.reject(error)
}
)
request.interceptors.response.use(
response => {
// 请求成功,从队列里删除该controller
const {url,method,removeCache=false} = response.config
if(removeCache) removeCacheRequest(`${url}&${method}`)
let res
if (response.config.downBlob) { // 下载文件
const json = {
blob: response.data,
headers: response.headers
}
res = json
} else {
res = response.data
}
const path = router.currentRoute.path
if (res.code === 100) { // 代表登录失效
if (loginInterception) {
store.clearUserStore()
const messageDom = document.getElementsByClassName('el-message')[0]
if (messageDom === undefined) {
ElMessage({
type: 'error',
message: '未登录或者登录失效,请重新登录',
onClose: () => {
if (path !== '/login') { // 在login 页就不要跳转了
router.push('/login')
}
}
})
}
}
}
return res
},
error => {
let code = 0
try {
code = error.response.data.status
} catch (e) {
}
if(isCancel(error)){
return Promise.reject({
msg:'重复请求,自动拦截并取消'
})
}else{
return Promise.reject(error)
}
}
)
/**
* @description: get请求
* @param {string} url 请求地址后缀
* @param {object} params 请求参数
* @param {object} config 请求配置
* @return {*}
*/
const get = (url, params, config) => {
const reqData = {
method: 'get',
url: url,
params
}
if (config) {
Object.assign(reqData, config)
}
return request(reqData)
}
/**
* @description: post请求
* @param {string} url 请求地址后缀
* @param {object} params 请求参数
* @param {object} config 请求配置
* @return {*}
*/
const post = (url, data, config) => {
const reqData = {
method: 'post',
url: url,
data
}
if (config) {
Object.assign(reqData, config)
}
return request(reqData)
}
/**
* @description: post请求
* @param {string} url 请求地址后缀
* @param {object} data 请求参数
* @param {object} params 请求参数
* @param {object} config 请求配置
* @return {*}
*/
const postAndGet = (url, data, params, config) => {
console.log(data, params)
const reqData = {
method: 'post',
url: url,
data,
params
}
if (config) {
Object.assign(reqData, config)
}
return request(reqData)
}
/**
* @description: post请求(参数拼接式,类get)
* @param {string} url 请求地址后缀
* @param {object} params 请求参数
* @param {object} config 请求配置
* @return {*}
*/
const postOfGet = (url, params, config) => {
const reqData = {
method: 'post',
url: url,
params
}
if (config) {
Object.assign(reqData, config)
}
return request(reqData)
}
/**
* @description: formData对象+get拼接式复合请求
* @param {*} url 请求地址后缀
* @param {*} formData 请求数据
* @param {*} config
* @param {*} config.params 拼接数据
* @return {*}
*/
const postOfForm = (url, formData, config) => {
const reqData = {
method: 'post',
url: url,
data: formData,
headers: { 'Content-Type': 'multipart/form-data' }
}
if (config) {
Object.assign(reqData, config)
}
return request(reqData)
}
export { request, get, post, postOfGet, postOfForm, postAndGet }