axios 重复请求,快速点击

起因

一个项目使用的是axios,遇到了用户短时间内,快速点击提交按钮,导致触发了多次请求,提交了多条记录。

解决办法

import axios from "axios";
import md5 from "js-md5";
import {
  Message
} from "element-ui";
import router from "../router";
import {
  generateRequestParamsSign,
  getToken,
  isHttps
} from "./commonUtils";
import Constants from "../constants";
import hostUrl from "./apiUrl";
export const baseUrl = hostUrl.url;


const CancelToken = axios.CancelToken;
let requestQueue = [];

// 请求拦截调用
function handleRequest( config ) {
  // HEX化确定唯一请求
  const requestId = md5.hex(config.data);
  const panding = requestQueue.filter(item => item.id === requestId);
  var cancel;
  if (panding.length) {
    // 这里是重点,实例化CancelToken时,对参数 c 进行立即调用,即可立即取消当前请求
    config.cancelToken = new CancelToken(c => {
      cancel = c;
      c(`拦截重复的请求`);
    });
  } else {
    // 如果请求不存在
    requestQueue.push({
      id: requestId,
      cancel: cancel
    });
  }
}

// 响应拦截调用
function handleResponse( config ) {
  const requestId = md5.hex(config.data);
  const reqQueue = requestQueue.filter(item => item.id === requestId);
  requestQueue = reqQueue;
}


function processingConfig(config) {
  if (config.method === "post" || config.method === "get") {
    if (config.data.apiCode === "undefined") {
      return new Error();
    }
    let apiCode = "";
    for (const key in config.data) {
      if (key === "apiCode") {
        apiCode = config.data[key];
        delete config.data.apiCode;
      }
    }

    let token = "";
    if (apiCode === "ifredomService.login") {
      token = "";
    } else if (!getToken(Constants.cookieName)) {
      Message({
        type: "error",
        message: "登录状态已过期,请重新登录!!"
      });
      router.push("/login");
    } else {
      token = getToken(Constants.cookieName);
    }
    config.data = generateRequestParamsSign(
      "ifredom",
      apiCode,
      token,
      config.data,
      "ifredom_2019"
    );
    config.data = qs.stringify(config.data);
  }
}

export const Axios = axios.create({
  baseURL: baseUrl,
  timeout: 10000,
  responseType: "json",
  // withCredentials: true, // 是否允许带cookie
  headers: {
    // 'content-type': 'application/json;charset=utf-8' // 会发option请求
    "content-type": "application/x-www-form-urlencoded" // 不会触发option请求
  }
});

// POST请求拦截 (对请求参数序列化)
Axios.interceptors.request.use(
  (config, callback) => {

    if (config.method === "post" || config.method === "get") {
      processingConfig(config);
    }
    if (config.method === "post") {
      handleRequest( config );
    }
    return Promise.resolve(config);
  },
  error => {
    Message({
      showClose: true,
      message: error,
      type: "error"
    });
    return Promise.reject(error);
  }
);
// 返回数据的判断校验
Axios.interceptors.response.use(
  response => {
    handleResponse(response.config);
    
    if (response.data && response.data.code + "" !== "0") {
      Message({
        showClose: true,
        message: response.data.msg,
        type: "error"
      });
      return Promise.reject(new Error(response.data.msg));
    }
    return Promise.resolve(response.data);
  },
  error => {
    Message({
      message: error.message,
      type: "error",
      duration: 3000
    });
    if (error.response) {
      return Promise.reject(error);
    }
  }
);

export default {
  install: function (Vue, Option) {
    Object.defineProperty(Vue.prototype, "$http", {
      value: Axios
    });
  }
};

------ 如果文章对你有用,感谢右上角 >>>点赞 | 收藏 <<<

你可能感兴趣的:(Vue.js,javascript)