乐趣区

关于javascript:axios源码学习关键知识点之取消请求

本文只关注 axios 源码之勾销申请这个知识点的实现,如想看残缺源码解析,请移步若川大佬的 axios 源码解析,axios 是基于 promise 封装的,看 axios 需先对 promise 有所理解

  1. 勾销申请的应用

     const CancelToken = axios.CancelToken;
     const source = CancelToken.source();
     var options = {
           url: 'xxxx',
           data: {},
           method: 'post',
           cancelToken: source.token
     };
     axios(options).then(function (res) {})
     // 调用 cancel 勾销申请
     source.cancel('申请勾销了');

    如上:调用 source.cancel 便可勾销申请
    疑难:为什么 source.cancel 能够勾销申请?

  2. 源码对于勾销申请的实现

    1. 先看 axios\lib\adapters\xhr.js 外面是什么时候勾销申请的,源码如下:

      if (config.cancelToken) {
            // Handle cancellation
            config.cancelToken.promise.then(function onCanceled(cancel) {if (!request) {return;}
              // 勾销申请
              request.abort();
              reject(cancel);
              // Clean up request
              request = null;
            });
          }

      可看出在 config.cancelToken.promise.then 外面勾销的
      疑难:config.cancelToken.promise.then 什么时候调的,为什么 source.cancel 能够触发 then 的执行?

      1. 勾销申请实现
        看源码之前。先看一个小例子:

        let t = new Promise((resolve) => {resolve('执行')
           })
           t.then(res => {console.log(res)
           })

        这里只有执行 t.then, ‘ 执行 ’ 就被打印了,如果我想想在任何须要的中央去执行 resolve(‘ 执行 ’),只能同过 setTimeout 去执行 t.then, 然而在 axios 源码外面 config.cancelToken.promise.then 的调用工夫曾经定死了,咱们只能通过 source.cancel 去管制 config.cancelToken.promise.then 的执行

        革新上方代码:

         let t = new Promise((resolve) => {
            // 把 resolve 援用存起来,须要执行的时候再执行
            delayedResolve = resolve
          })
           t.then(res => {console.log(res)
           })
          setTimeout(() => {delayedResolve('须要执行的时候在执行')
          }, 3000)

        能够看到,咱们能够灵便管制 delayedResolve 的调用工夫来触发 t.then 的执行
        上 axios 勾销申请的源码:

        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) {
              // Cancellation has already been requested
              return;
            }
            token.reason = new Cancel(message);
            resolvePromise(token.reason);
          });
        }
        CancelToken.source = function source() {
          var cancel;
          var token = new CancelToken(function executor(c) {cancel = c;});
          return {
            token: token, // 返回的一个构造函数
            cancel: cancel
          };
        };

        剖析:
        cancel 必定是一个函数,CancelToken 接管一个函数 executor,executor 再接管一个函数 cancel = function cancel(message),并将此函数复制给 CancelToken.source.cancel,cancel 外面调用了 CancelToken.promise 的 resolve。由此能够通过任意工夫调用 source.cancel 来触发 CancelToken.promise 的 resolve

退出移动版