1

由于接口响应速度等原因,在项目开发中经常需要处理重复点击导致多次调用接口的问题,针对每个接口调用单独处理相对繁琐,这里通过axios提供的拦截器实现对重复请求的统一拦截处理。

import axios from 'axios'
import md5 from 'js-md5'
let pending = {};// 网络请求记录map结构
let CancelToken = axios.CancelToken;
// 添加请求拦截器
axios.interceptors.request.use(config => {
// 通过请求url、method、params字段生成每个请求唯一的md5值
let key = md5(`${config.url}&${config.method}&${JSON.stringify(config.data)}`);
  config.cancelToken = new CancelToken(c => {
    if(pending[key]) {
      if(Date.now() - pending[key] > 5000) {
        // 同一个请求再次发起时距上次请求时间超过5s,删除对应的请求记录,重新发起请求,时间根据实际情况调整
        delete pending[key];
      } else {
        // 5s以内的已发起请求,取消重复发送请求
        c('repeated');
      }
    }
    // 记录当前的请求,如果是进行中的请求则更新标记时间戳
    pending[key] = Date.now();
  });
}, error => {
  return Promise.reject(error);
});

// 添加响应拦截

axios.interceptors.response.use(res => {
//response的config.url包含域名,需替换为空字符串,保证和request的url完全一致
  let key = md5(`${res.config.url.replace(/.*\/api/, '')}&${res.config.method}&${res.config.data}`);
  if(pending[key]) {
    // 请求响应完成,删除对应的请求记录
    delete pending[key];
  }
  return res;
}, err => {
  if(err.message !== 'repeated') {
    // 非取消重复请求的报错,给出错误提示
    let content = '系统错误!';
    if(window.navigator.onLine) {
      if(/timeout/.test(err)) {
        content = '请求超时!';
      }
    } else {
      content = '网络异常!';
    }
    alert(content);
  }
  return Promise.reject(err);
})

action
12 声望0 粉丝