文章目录
- [1. CancelToken 方法使用示例](#1. CancelToken 方法使用示例)
-
- [1.1 请求拦截 / 响应器写法](#1.1 请求拦截 / 响应器写法)
- [1.2 接口定义写法](#1.2 接口定义写法)
- [1.3 具体使用写法](#1.3 具体使用写法)
- [2. AbortController 方法使用示例(axios~v0.22.0 及以后版本)](#2. AbortController 方法使用示例(axios~v0.22.0 及以后版本))
-
- [2.1 请求拦截 / 响应器写法](#2.1 请求拦截 / 响应器写法)
- [2.2 接口定义写法](#2.2 接口定义写法)
- [2.3 具体使用写法](#2.3 具体使用写法)
1. CancelToken 方法使用示例
1.1 请求拦截 / 响应器写法
javascript
复制代码
// requer.js 文件
import router from '@/router'
import { ElMessage } from 'element-plus'
// 全版本兼容 CancelToken 方法 -- 示例
import axios, { CancelToken } from 'axios';
// import { getToken, setToken, getRootDomain } from './auth'
// 全局请求控制器
export const requestController = {
pendingRequests: new Map(),
addRequest (key, cancel) {
this.pendingRequests.set(key, cancel);
},
cancelRequest (key, message = '请求已取消') {
if (this.pendingRequests.has(key)) {
const cancel = this.pendingRequests.get(key);
cancel(message);
this.pendingRequests.delete(key);
}
},
removeRequest (key) {
this.pendingRequests.delete(key);
}
};
const service = axios.create({
url: '/',
})
service.interceptors.request.use(config => {
const requestKey = `${config.method}-${config.url}-${JSON.stringify(config.data || config.params)}`;
// 取消重复请求
requestController.cancelRequest(requestKey);
config.cancelToken = new CancelToken((cancel) => {
requestController.addRequest(requestKey, cancel);
});
return config;
},
(error) => {
// if(store.loading)
// Do something with request error
// console.log(error); // for debug
Promise.reject(error);
},
);
service.interceptors.response.use(
res => {
const { data } = res
const requestKey = `${res.config.method}-${res.config.url}-${JSON.stringify(res.config.data || res.config.params)}`;
requestController.removeRequest(requestKey);
if (data.code == 401) {
window.sessionStorage.clear()
router.replace('/login')
return Promise.reject(data)
}
if (data.code == 500) {
ElMessage({
type: 'error',
message: data?.message || '网络错误',
center: true,
})
return Promise.reject(data)
}
return data
},
(error) => {
if (axios.isCancel(error)) {
console.log('请求被取消:', error.message);
return new Promise(() => { });
}
// console.log('err' + error); // for debug
ElMessage({
message:
(error && error.message) ||
'网络错误或获取失败,请刷新后重试', // error.message,
type: 'error',
duration: 5 * 1000,
});
return Promise.reject(error);
},
)
export default service
1.2 接口定义写法
javascript
复制代码
// api/index.js 文件
import service, { requestController } from '@/utils/requer'
// 不需要主动取消请求写法
// export const userCopyAdd = (data) => {
// return service({
// url: '/api/user-copy/add',
// method: 'POST',
// data
// })
// }
// 需要主动取消请求写法
export const userCopyAdd = (data) => {
const request = {
service: () => {
return service({
url: '/api/user-copy/add',
method: 'POST',
data,
});
},
cancel: () => {
// 这里有个注意点,请求方式必须是小写,不论请求本身是怎么写的
const key = `post-/api/user-copy/add-${JSON.stringify(data)}`;
requestController.cancelRequest(key);
}
};
return request;
}
1.3 具体使用写法
javascript
复制代码
<template>
<!-- 取消重复请求 -- 由于接口响应速度比较快,需要将网络调整成3G网或者快速点击 -->
<!-- 请求的接口:/user-copy/add 需启动 nest-moogodb 项目,项目地址:https://gitee.com/kuxiao-smile/node-nest -->
<el-button size="small" @click="setUserCopyAdd">重复请求测试</el-button>
<el-button size="small" @click="cancelUserCopyAdd">取消请求测试</el-button>
</template>
<script setup>
import { ref } from 'vue';
import { userCopyAdd } from '@/api/index'
const ruleForm = ref({})
// 添加重复请求接口拦截
const setUserCopyAdd = () => {
// userCopyAdd(ruleForm.value)
userCopyAdd(ruleForm.value).service().then(res => {
ElMessage.success('添加成功')
}).catch(error => {
console.error('添加失败:', error); // 添加错误捕获
ElMessage.error('添加失败: ' + (error.message || '未知错误'));
})
}
// 取消请求
const cancelUserCopyAdd = () => {
userCopyAdd(ruleForm.value).cancel()
}
</script>
<style lang="less" scoped></style>
2. AbortController 方法使用示例(axios~v0.22.0 及以后版本)
2.1 请求拦截 / 响应器写法
javascript
复制代码
// requer.js 文件
import router from '@/router'
import { ElMessage } from 'element-plus'
// v0.22.0 及以后版本 ( 以前版本此方法无效 ) AbortController 方法 -- 使用示例
import axios from 'axios';
export const requestController = {
pendingRequests: new Map(),
addRequest(key, controller) {
this.pendingRequests.set(key, controller);
},
cancelRequest(key, message = '请求已取消') {
if (this.pendingRequests.has(key)) {
const controller = this.pendingRequests.get(key);
controller.abort(message);
this.pendingRequests.delete(key);
}
},
removeRequest(key) {
this.pendingRequests.delete(key);
}
};
// 创建axios实例
const service = axios.create({
baseURL: '/',
});
// request拦截器
service.interceptors.request.use(
(config) => {
const requestKey = `${config.method}-${config.url}-${JSON.stringify(config.data || config.params)}`;
// 取消重复请求
requestController.cancelRequest(requestKey);
// 使用AbortController
const controller = new AbortController();
config.signal = controller.signal;
requestController.addRequest(requestKey, controller);
return config;
},
(error) => {
// if(store.loading)
// Do something with request error
// console.log(error); // for debug
Promise.reject(error);
},
);
service.interceptors.response.use(
res => {
const { data } = res
const requestKey = `${res.config.method}-${res.config.url}-${JSON.stringify(res.config.data || res.config.params)}`;
requestController.removeRequest(requestKey);
if (data.code == 401) {
window.sessionStorage.clear()
router.replace('/login')
return Promise.reject(data)
}
if (data.code == 500) {
ElMessage({
type: 'error',
message: data?.message || '网络错误',
center: true,
})
return Promise.reject(data)
}
return data
},
(error) => {
if (axios.isCancel(error)) {
console.log('请求被取消:', error.message);
return new Promise(() => { });
}
// console.log('err' + error); // for debug
ElMessage({
message:
(error && error.message) ||
'网络错误或获取失败,请刷新后重试', // error.message,
type: 'error',
duration: 5 * 1000,
});
return Promise.reject(error);
},
)
export default service
2.2 接口定义写法
javascript
复制代码
// api/index.js 文件
import service, { requestController } from '@/utils/requer'
// 不需要主动取消请求写法
// export const userCopyAdd = (data) => {
// return service({
// url: '/api/user-copy/add',
// method: 'POST',
// data
// })
// }
// 需要主动取消请求写法
export const userCopyAdd = (data) => {
const request = {
service: () => {
return service({
url: '/api/user-copy/add',
method: 'POST',
data,
});
},
cancel: () => {
// 这里有个注意点,请求方式必须是小写,不论请求本身是怎么写的
const key = `post-/api/user-copy/add-${JSON.stringify(data)}`;
requestController.cancelRequest(key);
}
};
return request;
}
2.3 具体使用写法
javascript
复制代码
<template>
<!-- 取消重复请求 -- 由于接口响应速度比较快,需要将网络调整成3G网或者快速点击 -->
<!-- 请求的接口:/user-copy/add 需启动 nest-moogodb 项目,项目地址:https://gitee.com/kuxiao-smile/node-nest -->
<el-button size="small" @click="setUserCopyAdd">重复请求测试</el-button>
<el-button size="small" @click="cancelUserCopyAdd">取消请求测试</el-button>
</template>
<script setup>
import { ref } from 'vue';
import { userCopyAdd } from '@/api/index'
const ruleForm = ref({})
// 添加重复请求接口拦截
const setUserCopyAdd = () => {
// userCopyAdd(ruleForm.value)
userCopyAdd(ruleForm.value).service().then(res => {
ElMessage.success('添加成功')
}).catch(error => {
console.error('添加失败:', error); // 添加错误捕获
ElMessage.error('添加失败: ' + (error.message || '未知错误'));
})
}
// 取消请求
const cancelUserCopyAdd = () => {
userCopyAdd(ruleForm.value).cancel()
}
</script>
<style lang="less" scoped></style>