最近封装axios,应用到勾销机制,发现应用十分简便,那么axios是如何实现的呢?简略钻研了一下
应用形式
axios 如何勾销一个申请提供了两种应用模式:
- 第一种 调用CancelToken的静态方法source
const CancelToken = axios.CancelToken;const source = CancelToken.source();axios.post('/user/12345', { name: 'new name'}, { cancelToken: source.token})source.cancel('Operation canceled by the user.');
- 第二种 本人实例化
let cancel;axios.get('/user/12345', { cancelToken: new CancelToken(function executor(c) { cancel = c; })});cancel();
OK,能够看到应用非常简单,两种应用形式情理是一样的,分两步:
- 获取cancelToken实例,注入申请的配置参数
- 须要勾销的时候,调用 提供的cancel办法
剖析
剖析之前,用了几分钟思考了一下,可能是利用了状态机来管制的,具体怎么实现的,没想好。间接扒拉代码。
CancelToken.js
间接找CancelToken类,代码非常简单,如下:
function CancelToken(executor) { if (typeof executor !== 'function') { throw new TypeError('executor must be a function.'); } var resolvePromise; this.promise = new Promise(function promiseExecutor(resolve) { resolvePromise = resolve; }); var token = this; executor(function cancel(message) { if (token.reason) { return; } token.reason = new Cancel(message); resolvePromise(token.reason); });}CancelToken.prototype.throwIfRequested = function throwIfRequested() { if (this.reason) { throw this.reason; }};CancelToken.source = function source() { var cancel; var token = new CancelToken(function executor(c) { cancel = c; }); return { token: token, cancel: cancel };};
概括一下外围逻辑就是,在实例上挂载了一个 promise,而后把 promise的实例 和 更改promise状态的 resovle函数对外抛出。
还能够看到 提供的两种应用办法并没有本质区别。
在内部,把promise实例提供给 axios的配置参数,而后更改promsie状态的resolve函数,也就是cancel函数能够随便应用。
ok,到了这里就十分清朗了,也就是一个promsie管制的极简 状态机。
咱们有理由揣测,axios外部拿到promise实例,只须要挂载一个then回调,回调里调用 xmlHttpRequest的abort办法即可。
那么持续追踪验证一下是不是这么实现的。
adapters/http.js
搜寻关键词,能够看到第 284行,注册了回调勾销函数:
if (config.cancelToken) { // Handle cancellation config.cancelToken.promise.then(function onCanceled(cancel) { if (req.aborted) return; req.abort(); reject(cancel); });}
顺带还看到了timeout的解决:
if (config.timeout) { req.setTimeout(config.timeout, function handleRequestTimeout() { req.abort(); reject(createError('timeout of ' + config.timeout + 'ms exceeded', config, 'ECONNABORTED', req)); });}
嗯,意料之中,timeout的解决机制也是一样的。
思考
看完代码,豁然开朗,原来这么简略。然而咱们确不肯定能写出这么优雅的代码。
这个案例,是一个简略的状态机,利用promise的异步个性,把变更外部状态的控制权移交内部,说白了就是一个闭包的利用,咱们能够有条有理的讲什么是闭包,然而确不肯定能使用的很奇妙,这种思维形式十分值得学习。