在很多情况下,我们需要取消已发送的网络请求(场景:搜索框需要进行模糊匹配,发请求获取数据),这块主要就讲一下取消请求的过程(结合axios源码)。
先上一段代码,后面也会结合这个示例与源码进行阐述:
index.html :
<button id="btn1">发送请求</button>
<button id="btn2">取消请求</button>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
var btn1 = document.getElementById('btn1')
var btn2 = document.getElementById('btn2')
const CancelToken = axios.CancelToken;
let cancel;
btn1.onclick = function () {
axios.get('http://localhost:5000/data', {
cancelToken: new CancelToken(function executor(c) {
// executor 函数接收一个 cancel 函数作为参数
cancel = c;
})
}).then(res => {
console.log(res);
})
}
btn2.onclick = function () {
cancel()
}
</script>
node后台:
const express = require('express')
const cors = require('cors')
const app = express()
app.use(cors())
app.get('/data', (req, res) => {
setTimeout(() => {
res.send('hell0')
}, 2000 + Math.random() * 1000)
})
app.listen(5000,()=>{
console.log('服务器启动了');
})
首先需要注意的是,如果要让该请求可以取消的话,必须设置cancelToken属性。
axios相关源码:
// 将CancelToken构造函数挂载在axios上
axios.CancelToken = require('./cancel/CancelToken');
CancelToken.js:
function CancelToken(executor) {
if (typeof executor !== 'function') {
throw new TypeError('executor must be a function.');
}
var resolvePromise;
// this:CancelToken的实例对象,也就是我们上例中的配置对象的value值
// 在axios源码中就是通过config.CancelToken获取的
// 这段代码极为重要:它其实做了一件事情,在实例上挂载了promise属性,其属性值为Promise对象,并且把执行成功的resolve函数,保存在了外面,也就是说外面也可以调用该函数。
this.promise = new Promise(function promiseExecutor(resolve) {
resolvePromise = resolve;
});
var token = this;
// 执行器函数:注意一点,它只是赋值,并没有调用。只有当我们调用的时候,就会调用resolve(new Cancel(message))。
// 与上例对应:cancel函数就是参数c,cancel就是保存至全局的cancel函数,cancel()就是取消请求。
executor(function cancel(message) {
if (token.reason) {
// Cancellation has already been requested
return;
}
token.reason = new Cancel(message);
// new Cancel(message):取消的提示信息
resolvePromise(token.reason);
// 等价于:resolve(new Cancel(message)),执行this.promise的成功回调
});
}
module.exports = CancelToken;
xhr.js:
// 由于我们在配置中配置了cancelToken,所以会进入该判断语句。
if (config.cancelToken) {
// 取消请求:执行成功的回调。可以看出事实上我们是通过触发执行器函数的resolve(new Cancel(message)),然后调用的request.abort()从而达到取消请求的目的。
config.cancelToken.promise.then(cancel=> {
if (!request) {
return;
}
// 取消请求
request.abort();
// 返回拒绝promise
reject(cancel);
// 清空请求
request = null;
});
}
所以,取消请求的流程可以总结为:
1、配置cancelToken,
2、将执行器函数保存至全局,
3、执行器函数执行时,会调用成功的回调,其中包含取消请求以及返回拒绝的promise。
欢迎留言~~~