axios 中 cancel 请求的具体使用以及原理
具体使用
如果我们需要对 cancel 某请求,则需要传递 config.cancelToken 参数,简单使用如下
const CancelToken = axios.CancelToken
const source = CancelToken.source()
axios.get('/user', {
cancelToken: source.token
})
// 如果我们不想请求了,则执行如下代码即可
source.cancel('cancel')
如果熟悉原生的 XMLHttpRequest 对象的话,request 对象直接提供了 abort 函数用来取消请求。
但 axios 对使用方式进行了 Promise 化,我们是无法得到 request 对象的。哪 axios 是如何做到的呢
cancelToken 作用
查看使用方式也知道,我们需要对 config 多传递一个特定的 cancelToken 参数,其背后的代码大概是这样的
if (config.cancelToken) {
config.cancelToken.promise.then(resolve => {
// axios 内部肯定是可以获取到 request 对象的
if (!request) {
return;
}
request.abort();
// 执行 reject
reject(cancel);
// Clean up request
request = null;
})
}
看到这里好像有点似懂非懂的样子,source.token 有一个 promise 属性,如果该 promise 成功执行,则会执行我们熟悉的 request.abort 操作。由此看来,source.cancel 操作执行的应该是 promise 的 resolve 操作
CancelToken 原理
到这里,其实 CancelToken 的实现原理,大概也就了解的七七八八的,有一个 promise 属性,将该 promise 的 resolve 传递出去作为 cancel 函数。
最简单代码应该如下
function CancelToken() {
// 执行 resolvePromise 会取消请求
let resolvePromise
this.promise = new Promise(resolve => {
resolvePromise = resolve
})
}
axios 是将 token 和 cancel 操作分开的,通过一个 source 函数来生成 token 和 cancel 函数作为一个 source 对象。因此对于 token 中的 resolvePromise 如何传递出去呢,答案是通过回调函数。下面先看 source 函数简单实现
CancelToken.prototype.source = function() {
let cancel
var token = new CancelToken(function executor(c) {
cancel = c;
});
return {
token,
cancel
}
}
接下来进一步完善 CancelToken 函数
function CancelToken(executor) {
// 执行 resolvePromise 会取消请求
let resolvePromise
this.promise = new Promise(resolve => {
resolvePromise = resolve
})
const token = this;
executor(function cancel(message) {
if (token.reason) {
// 如果已经取消
return;
}
token.reason = new Cancel(message);
resolvePromise(token.reason);
});
}
是不是挺简单的哈!