Axios简单封装cancelToken
Request & PendingPromiseStorage
import axios from 'axios'
import Base64 from './Base64'
class PendingPromiseStorage {
constructor() {
this._data = new Map()
}
setItem(payload) {
let { uid, item } = payload
this._data.set(uid, item)
}
getItem(uid) {
return this._data.get(uid)
}
removeItem(uid) {
this._data.delete(uid)
}
hasItem(uid) {
return this._data.has(uid)
}
cancelBefore(config) {
let { uid, url } = config
if (!this.hasItem(uid)) {
return
}
let item = this.getItem(uid)
let msg = `axios cancel (before cancel) ${url}`
item.cancel(msg)
this.removeItem(uid)
}
cancelAfter(config, cancel) {
let { uid, url } = config
if (!this.hasItem(uid)) {
return
}
let item = this.getItem(uid)
let msg = `axios cancel (after cancel) ${url}`
if (cancel !== item.cancel) {
setTimeout(() => {
cancel(msg)
})
}
}
}
PendingPromiseStorage.getPendingUID = (config) => {
return Base64.encode(`${config.url}${config.method}${JSON.stringify(config.params)}${typeof config.data === 'string' ? config.data : JSON.stringify(config.data)}`)
}
const pendingPromiseStorage = new PendingPromiseStorage()
const interceptors = {
request: {
success(config) {
console.log('cancelToken:', config.cancelToken)
if (Object.hasOwnProperty.call(config, 'cancelToken')
&& (config.cancelToken === 'before' || config.cancelToken === 'after')
) {
let cancelToken = config.cancelToken
let uid = config.uid = PendingPromiseStorage.getPendingUID(config)
if (cancelToken === 'before') {
pendingPromiseStorage.cancelBefore(config)
}
let cancel = null
config.cancelToken = new axios.CancelToken(c => {
cancel = c
let item = {
uid,
createTime: Date.now(),
cancelToken,
cancel: c
}
if (
(cancelToken === 'before')
|| (cancelToken === 'after' && !pendingPromiseStorage.hasItem(uid))
) {
pendingPromiseStorage.setItem({ uid, item })
}
})
if (cancelToken === 'after') {
pendingPromiseStorage.cancelAfter(config, cancel)
}
}
return config
},
failed(error) {
let { config = {} } = error
pendingPromiseStorage.removeItem(config.uid)
return Promise.reject(error)
}
},
response: {
success(response) {
let { config } = response
pendingPromiseStorage.removeItem(config.uid)
return response
},
failed(error) {
let { config = {} } = error
pendingPromiseStorage.removeItem(config.uid)
return Promise.reject(error)
}
}
}
class Request extends axios.create {
constructor(config) {
super(config)
this.interceptors.request.use(interceptors.request.success, interceptors.request.failed)
this.interceptors.response.use(interceptors.response.success, interceptors.response.failed)
}
}
const instanceInterceptors = {
request: {
success(config) {
return config
},
failed(error) {
return Promise.reject(error)
}
},
response: {
success(config) {
return config
},
failed(error) {
return Promise.reject(error)
}
}
}
let instance = new Request({
name: 'Test-cancelToken',
baseURL: '/dev-api/',
timeout: 10000
})
instance.interceptors.request.use(instanceInterceptors.request.success, instanceInterceptors.request.failed)
instance.interceptors.response.use(instanceInterceptors.response.success, instanceInterceptors.response.failed)
export default instance
Test
1、取消前一个请求
export default {
methods: {
login() {
return request({
url: '/user/login',
method: 'post',
data: {
username: 'admin',
},
cancelToken: 'before'
})
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err)
})
}
}
}
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/68588f097b85285c2c68afc3126c6b7a.png)
2、取消下一个请求
export default {
methods: {
login() {
return request({
url: '/user/login',
method: 'post',
data: {
username: 'admin',
},
cancelToken: 'after'
})
.then(res => {
console.log(res)
})
.catch(err => {
console.log(err)
})
}
}
}
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/1c156eaf2d504a3075c39ee34a23f857.png)