axios 取消請求

這是我參與更文挑戰的第7天,活動詳情查看: 更文挑戰ios

當切換步驟或切換tab等狀況,前一個組件中發起的請求可能還在進行中,用戶就已經退出了步驟流程,也多是切換到了其餘的tab頁面,以前的請求還在進行中,若是不去處理未完成的請求,會極大地影響頁面性能,甚至致使後續的請求超時,或者數據處理不正確,頁面展現錯誤等等axios

對於以上相似的問題,咱們就須要知道如何取消請求markdown

官方示例

const CancelToken = axios.CancelToken;
let cancel;

axios.get('/user/12345', {
  cancelToken: new CancelToken(function executor(c) {
    // executor 函數接收一個 cancel 函數做爲參數
    cancel = c;
  })
});

// cancel the request
cancel();
複製代碼

在請求配置之中實例化axios上的CancelToken方法,回調函數的返回值就是取消當前請求的方法:cancel,只須要把cancel保存到一個地方就能夠隨時調用,用來取消這個請求網絡

在實際項目中咱們每每不會像官網例子中那樣使用,更多的是在axios的攔截器中作全局配置管理,須要對上面的代碼進行一些改變函數

項目具體實現

項目中使用 Vuex 和 axios 請求和響應攔截器,在 axios 請求攔截器中實例化cancelToken而後把回調的取消請求方法,以請求的函數名爲 key ,以取消請求的方法爲 val ,註冊到 Vuex 中,那麼就能夠在在這個請求週期內利用Vuex去調用這個方法,用來取消這個請求。post

axios 攔截器性能

Vue 狀態管理模式 -- Vuexui

Vuex

store 文件夾中相關 modules 配置中增長 cancel 相關 state,actions 等this

const state = {
  cancel: {},
}

const mutations = {
  CANCEL(state, { funNames = [], msg = "用戶手動取消網絡請求" }) {
    if (!Object.keys(state.cancel).length) {
      return false
    }
    for (const key in state.cancel) {
      if (state.cancel.hasOwnProperty(key)) {
        if (funNames.includes(key)) {
          if (!state.cancel[key].response) {
            state.cancel[key].cancel(msg);
            state.cancel[key].response = true;
          }
        }
      } else {
        return false
      }
    }
  },
  SET_CANCEL(state, { cancel, funName }) {
    state.cancel[funName] = { cancel, response: false };
  },
  RESPONSE(state, funName) {
    if (Object.keys(state.cancel).includes(funName)) {
      state.cancel[funName].response = true;
    }
  },
}

const actions = {
  setCancel({ commit }, fn){
    commit('SET_CANCEL', fn)
  },
  response({ commit }, res){
    commit('RESPONSE', res)
  },
  cancel({ commit }, res) {
    commit('CANCEL', res)
  }
}

複製代碼

Axios

攔截器中配置 cancel 相關攔截處理url

import axios from "axios";
import store from "@/store";

var instance = axios.create({
  timeout: 30000,
  withCredentials: true
});

const CancelToken = axios.CancelToken;

// 請求攔截
instance.interceptors.request.use(
  req => {
    req.cancelToken = new CancelToken(cancel => {
      let url = req.url
      let str = url.split('/')
      str = Array.from(new Set(str))
      let index = str.length - 1
      let funName = str[index]
      store.dispatch("setCancel", { cancel, funName: funName })
    });
    return req;
  },
  err => Promise.reject(err)
);

// 響應攔截
instance.interceptors.response.use(
  function (response) {
    store.dispatch("response", response.config.funName);
    if (response.status === 200 && response.data.request_id) {
      if (response.data.code == 0) {
        return response.data;
      } else {
        let msg = response.data.msg
        Message.error({
          message: msg,
          duration: 3000,
          center: true,
          offset: 50,
          showClose: true
        });
        return Promise.reject(error);
      }
    }
    return response;
  },
複製代碼

調用

以上配置好後,就能夠在須要的業務方法中調用

funNames 設置須要取消的請求API名,就能夠同時取消一個或多個發送中的請求

handleCancel() {
    this.$store.dispatch("cancel", { funNames: ["flavors","transerver_info"] })
}
複製代碼

快試試吧~

相關文章
相關標籤/搜索