原生ajax及axios取消接口請求的方式

原生ajax中取消請求的方法

const xhr = new XMLHttpReques()
xhr.open('GET', '/api')
xhr.onreadstatechange(() => {
  if(xhr.readState === '4' && /^2\d{2}/.test(xhr.status)) {
    // sucess
  }
})
xhr.send()

// 取消請求
xhr.abort()

axios中取消同一時間的屢次請求

最多見的案例就是當咱們點擊按鈕須要去請求數據,若是按鈕沒有坐任何限制的話,當快速屢次點擊按鈕,可能會同時發出好幾條相同的請求,形成服務器壓力,也有可能形成頁面數據不對,此時咱們通常經常使用的方法就是在axios的全局攔截中作一些限制和判斷來規避這種操做javascript

import axios from 'axios'

// 將正在請求的地址存儲起來
const pending = []
const CancelToken = axios.CancelToken
/**
 * config 請求的axios的配置信息
 * c框架中用於取消的回調,在這也會用來判斷當前是請求階段仍是返回階段
*/
const removePending = (config, c) => {
  const url = config.url
  const index = pending.findIndex(i => i === `${url}&${config.method}`)
  // 判斷要請求的的地址有沒有在pending中
  if (index > -1) {
    c ? c('數據請求中……') : pending.splice(index, 1)
  } else {
    c && pending.push(`${url}&${config.method}`)
  }
}
// 超時設置
axios.defaults.timeout=5000

axios.interceptors.request.use(function(config) {
  // 請求以前判斷並添加到pending
  config.cancelToken = new CancelToken(c => {
    removePending(config, c)
  })
  return config
},function (error) {
  return Promise.reject(error)
})

/*對響應攔截*/
axios.interceptors.response.use(function (response) {
    const res=response.data
    // 請求回來後刪除pending存儲
    removePending(response.config)
    if(response.status !== 200){
      return Promise.reject(res)
    }else{
      return res;
    }
  }, function (error) {
    // 請求回來後刪除pending存儲
    error.config && removePending(error.config)
    return Promise.reject(error);
  });

axios取消生意tabs中未返回的請求

在一個帶有tabs的頁面中:
tabs
若是咱們點擊"5萬如下",此時出發加載數據,當頁面數據未返回的時候,又點擊了"5-10萬",此時會再次去請求數據,若是"5萬如下"的數據返回的比較慢,可能會將"5-10萬"返回的數據給頂掉,此時頁面顯示的數據雖然tags在"5-10萬",可是其實顯示的是上一個標籤的數據;因此咱們應該在切換標籤的時候,將當前標籤未返回的請求取消掉來防止這種混亂的事情發生;在vue模版頁面中:html

export default {
  data() {
    return {
      list: null,
      cancel: null
    }
  },
  create() {
    this.getLists()
  }
  methods: {
    // 獲取數據
    getLists() {
      const CancelToken = this.axios.CancelToken
      this.axios.get('/api',{
        cancelToken: new CancelToken(c => {
            // 調用c就能夠取消此請求
            this.cancel = c
          })
      }).then(result => {
        this.lists = result.data
      })
    },
    // 每次切換標籤時先調用此函數,就能夠取消請求
    cancelAxios() {
      this.cancel()
    },
    changeTabs() {
      this.cancelAxios()
      this.getLists()
    }
  },
}

axios源碼實現

源碼路徑:axios/lib/cancel/CancelToken.jsvue

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

function CancelToken(executor) {
  if (typeof executor !== 'function') {
    throw new TypeError('executor must be a function.');
  }
  // 將new Promise裏面的reslove付值給外部的resolvePromise,能夠方便在外面控制promise內部的狀態改變
  var resolvePromise;
  this.promise = new Promise(function promiseExecutor(resolve) {
    resolvePromise = resolve;
  });

  var token = this;
  //上例中new CancelToken穿進去的c就是此處的cancel函數,調用c就至關於調用cancel函數
  executor(function cancel(message) {
    if (token.reason) {
      return;
    }

    token.reason = new Cancel(message);
    // 更改promise的狀態,狀態改變後會執行下面的then方法
    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
  };
};

module.exports = CancelToken;

上接resolvePromise方法
地址: axios/lib/adapters/xhr.jsjava

if (config.cancelToken) {
  // 上面執行完取消後resolvePromise,會觸發下面的then方法
  // 取消請求
  config.cancelToken.promise.then(function onCanceled(cancel) {
    if (!request) {
      return;
    }

    request.abort();
    reject(cancel);
    // Clean up request
    request = null;
  });
}

所學有限,若是有什麼地方分析錯誤,能夠評論出來
原文地址ios

相關文章
相關標籤/搜索