实例使用
const CancelToken = axios.CancelToken; let cancel; axios.get('/data', { cancelToken: new CancelToken(function executor(c) { // executor 函数接收一个 cancel 函数作为参数 // 把cancel函数传递给外面,使得外面能控制执行取消请求 cancel = c; }) }); // cancel the request cancel();
从source 开始
CancelToken.source = function source() { var cancel; var token = new CancelToken(function executor(c) { // c 就是CancelToken中给executor传入的cancel方法 cancel = c; }); return { token: token, cancel: cancel }; }; module.exports = CancelToken;
CancelToken.source 返回一个对象
{ token: token, cancel: cancel };
token 是 CancelToken实例 , 用来区别不同对象
CancelToken 接受一个函数作为对象,将且赋值给外部进行调用,外部接受类似字符串这些提示信息, 传递到内部时经过一个回调函数cancel
而cancel 是内部来结束请求的方法,用来更新promise 状为fullfill
// axios/lib/cancel/CancelToken.js 'use strict'; var Cancel = require('./Cancel'); function CancelToken(executor) { if (typeof executor !== 'function') { throw new TypeError('executor must be a function.'); } /** * 定义一个将来能执行取消请求的promise对象,当这个promise的状态为完成时(fullfilled), * 就会触发取消请求的操作(执行then函数)。而执行resolve就能将promise的状态置为完成状态。 * 这里把resolve赋值给resolvePromise,就是为了在这个promise外能执行resolve而改变这个promise的状态 * 注意这个promise对象被赋值给CancelToken实例的属性promise,将来定义then函数就是通过这个属性得到promise */ var resolvePromise; this.promise = new Promise(function promiseExecutor(resolve) { resolvePromise = resolve; }); /** * 将CancelToken实例赋值给token * 执行executor函数,将cancel方法传入executor, * cancel方法可调用resolvePromise方法,即触发取消请求的操作 */ var token = this; executor(function cancel(message) { if (token.reason) { // 取消已响应 返回 return; } token.reason = new Cancel(message); // 这里执行的就是promise的resolve方法,改变状态 resolvePromise(token.reason); }); }
将 resolve 函数执行交给外部
var resolvePromise; this.promise = new Promise(function promiseExecutor(resolve) { resolvePromise = resolve; });
最终实现取消请求
config 对象是 axios 的请求配置对象
config.cancelToken.promise是通过源码的this.promise的得到,只要 cancel() 执行,就会走这个promise的reslove方法,调用浏览器原生提供的request.abort()方法,达到取消请求的目的
if (config.cancelToken) { // 如果配置了cancelToken属性 // 当promise为完成态时,这个then函数执行,即执行取消请求 config.cancelToken.promise.then(function onCanceled(cancel) { if (!request) { return; } // 取消ajax请求 request.abort(); reject(cancel); // Clean up request request = null; }); }