CancelToken 介绍
axios中用于取消请求的方法
使用
-
可以使用
CancelToken.source
工厂方法创建 cancel token,像这样:const CancelToken = axios.CancelToken; const source = CancelToken.source(); axios.get('/user/12345', { cancelToken: source.token }).catch(function(thrown) { if (axios.isCancel(thrown)) { console.log('Request canceled', thrown.message); } else { // 处理错误 } }); axios.post('/user/12345', { name: 'new name' }, { cancelToken: source.token }) // 取消请求(message 参数是可选的) source.cancel('Operation canceled by the user.');
-
还可以通过传递一个 executor 函数到
CancelToken
的构造函数来创建 cancel token:const CancelToken = axios.CancelToken; let cancel; axios.get('/user/12345', { cancelToken: new CancelToken(function executor(c) { // executor 函数接收一个 cancel 函数作为参数 cancel = c; }) }); // cancel the request cancel();
注意: 可以使用同一个 cancel token 取消多个请求
例子:重复请求处理
思路:新建一个数组存请求相关信息,在请求拦截中进行对当前请求进行处理,如果之前请求过则提示用户不要重复请求,直接中断当前请求,如果没请求过则将当前请求信息添加到数组中。在响应拦截中对于已经返回的请求做删除操作,确保可以在请求返回成功后再次请求。
import axios from 'axios'
import { message, Loading, Notification } from 'element-ui'
const instance = axios.create({
'Content-Type': 'application/json;charset=UTF-8',
'timeout': 20000
})
let loading = ''
let map = []
instance.interceptors.request.use(
config => {
if (config.isLoading) {
// 开启loading
loading = Loading.service({
lock: true,
text: '拼命加载中...',
background: 'rgba(0, 0, 0, 0.7)'
})
} else {
let cancel
config.cancelToken = new axios.CancelToken(function (c) {
cancel = c
})
let matchIndex = findMatchIndex (map, config)
if (matchIndex !== -1) {
Notification({
title: '提示',
message: '请不要重复提交',
type: 'error'
})
cancel('请求中断')
} else {
map.push({
url: config.url,
method: config.method,
params: config.params
})
}
}
return config
},
error => {
return Promise.reject(error)
}
)
instance.interceptors.response.use(
response => {
let { config } = response
let matchIndex = findMatchIndex (map, config)
console.log(matchIndex, 'matchIndex')
if (matchIndex !== -1) {
map.splice(matchIndex, 1)
}
if (config.isLoading) {
loading.close()
}
return response.data
},
error => {
console.log(error, 'error')
if (error.message === '请求中断') {
return Promise.reject(error)
}
loading.close()
// 通用错误处理
let normalErrorCodes = [400, 401, 404]
if (normalErrorCodes.includes(error.response.status)) {
message.error(error.response.data.msg || '请求错误')
}
return Promise.reject(error)
}
)
export default {
post (url, params = {}) {
const { isLoading = true } = params
return instance({
method: 'post',
url: url,
data: params,
timeout: 20000,
isLoading
})
},
get (url, params = {}) {
const { isLoading = true } = params
return instance({
method: 'get',
url: url,
params,
isLoading
})
},
delete (url, params = {}) {
let { isLoading = true } = params
return instance({
method: 'delete',
url: url,
params,
isLoading
})
},
put (url, params = {}) {
let { isLoading = true } = params
return instance({
method: 'put',
url: url,
data: params,
isLoading,
timeout: 20000
})
}
}
function findMatchIndex (map, config) {
return map.findIndex((item) => {
return (item.url === config.url && item.method === config.method && diff(item.params, config.params))
})
}
function diff(obj1, obj2) {
if (Object.keys(obj1).length !== Object.keys(obj2).length) {
return false
}
let obj1Keys = Object.keys(obj1)
for (let i = 0; i < obj1Keys.length; i++) {
if (obj1[obj1Keys[i]] !== obj2[obj1Keys[i]]) {
return false
}
}
return true
}