使用CancelToken來取消請求


axios的config中提供了一個cancelToken屬性,可以通過傳遞一個新的CancelToken對象來在請求的任何階段關閉請求。

CancelToken.js

'use strict';

var Cancel = require('./Cancel');

/**
 * A `CancelToken` is an object that can be used to request cancellation of an operation.
 *
 * @class
 * @param {Function} executor The executor function.
 */
//CancelToken構造函數,CancelToken是一個用於取消操作的對象
//CancelToken跳頁面后取消掉還在pending狀態的請求以提高性能
function CancelToken(executor) {
  if (typeof executor !== 'function') {//如果executor不是function,拋出錯誤
    throw new TypeError('executor must be a function.');
  }

  var resolvePromise;
  this.promise = new Promise(function promiseExecutor(resolve) {
    resolvePromise = resolve;
  });
  //CancelToken對象上的promise屬性,一個promise對象,resolve方法存下來到resolvePromise里

  var token = this;//當前CancelToken對象
  executor(function cancel(message) {
    if (token.reason) {
      //如果CancelToken對象上已經存在reason屬性,說明已經請求過取消操作了
      // Cancellation has already been requested
      return;
    }

    token.reason = new Cancel(message);//給當前CancelToken對象上設置reason屬性,是一個Cancel對象
    resolvePromise(token.reason);//調用resolve方法,參數是當前CancelToken對象上的reason屬性
    //用戶調用cancel方法后會對當前cancelToken對象上的promise改變其狀態為resolve,會運行適配器中的resolve回調來終止請求
  });
}

/**
 * Throws a `Cancel` if cancellation has been requested.
 */
//如果取消操作已經請求過了,就拋出Cancel對象的信息,也就是CancelToken對象的reason屬性
CancelToken.prototype.throwIfRequested = function throwIfRequested() {
  if (this.reason) {//如果當前CancelToken對象上有reason屬性,直接拋出
    throw this.reason;
  }
};

/**
 * Returns an object that contains a new `CancelToken` and a function that, when called,
 * cancels the `CancelToken`.
 */
//CancelToken類上的source靜態方法
//直接返回一個新建好的CancelToken對象和取消方法,方便使用,差不多就是工廠模式的意思
//返回一個對象包含兩個屬性,一個token屬性是一個CancelToken新實例,另一個cancel屬性是一個取消方法
//cancel取消方法對應CancelToken構造函數中的cancel方法,用戶取消請求的時候直接調用就可以了
CancelToken.source = function source() {
  var cancel;
  var token = new CancelToken(function executor(c) {
    cancel = c;
  });
  return {
    token: token,
    cancel: cancel
  };
};

module.exports = CancelToken;
Cancel.js
'use strict';

/**
 * A `Cancel` is an object that is thrown when an operation is canceled.
 *
 * @class
 * @param {string=} message The message.
 */
//Cancel對象構造函數,cancel對象是當請求被取消的時候會拋出的對象
function Cancel(message) {
  this.message = message;//Cancel對象上的message屬性
}

Cancel.prototype.toString = function toString() {//返回將Cancel對象的message屬性的字符串提示
  return 'Cancel' + (this.message ? ': ' + this.message : '');
};

Cancel.prototype.__CANCEL__ = true;//Cancel原型上的__CANCEL__內部屬性,默認為true

module.exports = Cancel;
isCancel.js
'use strict';

module.exports = function isCancel(value) {
  //判斷請求失敗時的錯誤對象是不是Cancel對象
  return !!(value && value.__CANCEL__);
};

cancelToken用法

自己存一個變量把cancel方法存下來,需要cancel的時候調用即可。

var CancelToken = axios.CancelToken;
var cancel;
 
axios.get('/user/12345', {
  cancelToken: new CancelToken(function executor(c) {
    // An executor function receives a cancel function as a parameter
    cancel = c;
  })
});
 
// cancel the request
cancel();

或者使用工廠模式創建cancelToken對象傳入也可以

var CancelToken = axios.CancelToken;
var source = CancelToken.source();
 
axios.get('/user/12345', {
  cancelToken: source.token
}).catch(function(thrown) {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
    // handle error
  }
});
 
axios.post('/user/12345', {
  name: 'new name'
}, {
  cancelToken: source.token
})
 
// cancel the request (the message parameter is optional)
source.cancel('Operation canceled by the user.');

在vue中使用的時候可以新建一個全局變量數組,專門存放所有請求的cancel方法,在axios的請求攔截器中將cancel插入全局變量數組中,當路由切換的時候,在路由鈎子里遍歷這個數組,調用所有的cancel方法,將上一個頁面還未完的請求取消,這樣就可以加快頁面的加載,避免不必要的等待。

var CancelToken = axios.CancelToken;

axios.interceptors.request.use((config) => {//在請求攔截器中為每一個請求添加cancelToken,並將cancel方法存入全局數組中保存
  config.cancelToken = new CancelToken((c) => {
    Vue.prototype.__cancels__.push(c);
  });
  return config;
}, (error) => {
  return Promise.reject(error);
});

router.beforeEach((to, from, next) => {//當路由切換頁面的時候,遍歷全局數組,將上一個頁面的所有請求cancel掉
  Vue.prototype.__cancels__.forEach((cancel) => {
    cancel();
  });
  Vue.prototype.__cancels__ = [];
})

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM