1. 程式人生 > 其它 >axios 原始碼取消請求解析

axios 原始碼取消請求解析

axios有兩種中斷請求的方法

1.CancelToken.source

const CancelToken = axios.CancelToken; const source = CancelToken.source();

axios.post('/test', { value: '測試' }, { cancelToken: source.token })
source.cancel('取消請求');

2.通過CancelToken建構函式進行取消

const CancelToken = axios.CancelToken;
let cancel;
axios.get(
"/test/user", { cancelToken: new CancelToken(function executor(c){ cancel = c }) }) cancel("取消請求")

主要程式碼:

function CancelToken(executor) {
  if (typeof executor !== 'function') {
    throw new TypeError('executor must be a function.');
  }

  var resolvePromise;
    
//給例項繫結一個promise,promsie 狀態為pending,只有呼叫resolvePromise 方法時this.promise變為fulfilled狀態
this.promise = new Promise(function promiseExecutor(resolve) { resolvePromise = resolve; }); var token = this; // eslint-disable-next-line func-names this.promise.then(function(cancel) { if (!token._listeners) return; var i; var l = token._listeners.length; for (i = 0; i < l; i++) { token._listeners[i](cancel); } token._listeners
= null; }); // eslint-disable-next-line func-names this.promise.then = function(onfulfilled) { var _resolve; // eslint-disable-next-line func-names var promise = new Promise(function(resolve) { token.subscribe(resolve); _resolve = resolve; }).then(onfulfilled); promise.cancel = function reject() { token.unsubscribe(_resolve); }; return promise; }; //通過Cancel函式創造一個取消原因資訊 executor(function cancel(message) { if (token.reason) { // Cancellation has already been requested return; } //token.reason 就是我們呼叫cancel方法時傳遞的資訊 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
};
};

在CancelToken.js中,發現上面兩種中斷請求的方法執行的都是同一個方法,

  executor(function cancel(message) {
    if (token.reason) {
      // Cancellation has already been requested
      return;
    }
     
    token.reason = new Cancel(message);
    resolvePromise(token.reason);
  });
function Cancel(message) {
  this.message = message;
}

token是指建立的CancelToken例項,判斷是否有reason這個屬性,有則說明已經發起取消請求了直接return,沒有就通過Cancel建構函式建立一個例項, 呼叫resolvePromise方法。

  var resolvePromise;

  this.promise = new Promise(function promiseExecutor(resolve) {
    resolvePromise = resolve;
  });

在建立CancelToken例項時,新增一個屬性promise為Promsie的 例項,且狀態為pending,將resolve方法賦值給resolvePromise.這樣resolvePromise就像取消請求的開關,只有呼叫了resolvePromsie方法才能執行promise鏈.

if (config.cancelToken || config.signal) {
      // Handle cancellation
      // eslint-disable-next-line func-names
      onCanceled = function(cancel) {
        if (!request) {
          return;
        }
        reject(!cancel || (cancel && cancel.type) ? new Cancel('canceled') : cancel);
        request.abort();
        request = null;
      };
config.cancelToken && config.cancelToken.subscribe(onCanceled);
CancelToken.prototype.subscribe = function subscribe(listener) {
  if (this.reason) {
    listener(this.reason);
    return;
  }

  if (this._listeners) {
    this._listeners.push(listener);
  } else {
    this._listeners = [listener];
  }
};

xhr.js根據cancelToken呼叫subscribe方法,當this.reason存在時呼叫 XMLhttpRquest取消方法。this.reason就是前面Cancel生成的例項。

以上就是axios取消請求的基本流程,