axios之cancelToken原理以及使用
- 背景:工作中遇到,学习记录下,方便以后查阅
cancelToken
在真实项目中,当路由已经跳转,而上一页的请求还在pending状态,如果数据量小还好,数据量大时,跳到新页面,旧的请求依旧没有停止,这将会十分损耗性能,这时我们应该先取消掉之前还没有获得相应的请求,再跳转到页面。这里axios给我们提供了一个方法:
cancelToken其实就是用来取消Ajax请求的
基本用法
let source = axios.CancelToken.source()
axios.interceptors.request.use((request) => {
request.cancelToken = source.token
return request
})
router.then((lib) => {
lib.default.beforeEach((to, from, next) => {
source.cancel()
source = axios.CancelToken.source()
next()
})
})
取消请求之后,会进入error,在里面处理一下如果是取消请求,就不报错
axios.interceptors.response.use(
(response) => {
return response
},
(error) => {
if (axios.isCancel(error)) {
console.log('request cancel', JSON.stringify(error))
return new Promise(() => {})
}
return Promise.reject(error)
}
)
实现原理
promise只有三种状态,pending(等待),resolved(成功),rejected(失败)。
它的本质就是在解决如何取消一个已经执行的promise本身
- 源码部分
function Cancel(message) {
this.message = message // 可以传递取消请求的原因
}
function CancelToken(executor) {
// 判断executor是一个函数,不然就报错
if (typeof executor !== 'function') {
throw new TypeError('executor must be a function')
}
var resolvePromise
this.promise = new Promise(function promiseExecutor(resolve) {
resolvePromise = resolve // 关键代码1
})
var token = this
// 以上token现在有一个promise属性,是一个未成功的promise对象
executor(function cancel(message) {
if (token.reason) {
return
}
token.reason = new Cancel(message)
resolvePromise(token.reason) // 关键代码2:把接收到的“取消请求信息”token.reason传递给下一个then中成功函数作为参数
})
}
CancelToken.prototype.throwIfRequested = function throwIfRequested() {
if(this.reason) {
throw this.reason
}
}
// source方法
CancelToken.source = function source() {
var cancel
var token = new CancelToken(function executor(c) {
cancel = c // 关键代码3:实现“在他处取消请求”,与上面“终止一个promise”异曲同工
})
return {
token: token,
cancel: cancel
}
}
module.exports = CancelToken
source()函数
source方法很简单,就是返回一个具有token和cancel属性的对象,但是token和cancel都是通过CancelToken这个构造函数来的
token
source.token是一个实例化对象,是一个未成功的promise对象
cancel()函数
source.cancel就是用来触发取消请求的函数。
cancel执行,给token加了一个reason属性,
Cancel特别简单就是给实例化对象添加一个message属性,所以现在token.reason是一个具有message属性的对象了。