axios 防止重复提交全局统一拦截(转)

3,522 阅读1分钟

1、取消模式

let pending = []; //声明一个数组用于存储每个ajax请求的取消函数和ajax标识
let cancelToken = axios.CancelToken;
let removePending = (config) => {
    for(let p in pending){
        if(pending[p].u === config.url + '&' + config.method) { //当当前请求在数组中存在时执行函数体
            pending[p].f(); //执行取消操作
            pending.splice(p, 1); //把这条记录从数组中移除
        }
    }
}
 
//添加请求拦截器
axios.interceptors.request.use(config=>{
     removePending(config); //在一个ajax发送前执行一下取消操作
     config.cancelToken = new cancelToken((c)=>{
        // 这里的ajax标识我是用请求地址&请求方式拼接的字符串,当然你可以选择其他的一些方式
        pending.push({ u: config.url + '&' + config.method, f: c });  
    });
     return config;
   },error => {
     return Promise.reject(error);
   });
 
//添加响应拦截器
axios.interceptors.response.use(response=>{
      removePending(res.config);  //在一个ajax响应后再执行一下取消操作,把已经完成的请求从pending中移除
      return response;
   },error =>{
      return { data: { } }; 返回一个空对象,否则控制台报错
   });



2、防抖模式

zacharykwan.com/2018/05/22/…


// http.js

import { debounce } from "../debounce";

let pendingArr = [];
let CancelToken = axios.CancelToken;
let pendingHandler = (flag, cancelFn) => {
    if (pendingArr.indexOf(flag) > -1) {
        if (cancelFn) {
            cancelFn(); // cancel
        } else {
            pendingArr.splice(pendingArr.indexOf(flag), 1); // remove flag
        }
    } else {
        if (cancelFn) {
            pendingArr.push(flag);
        }
    }
};
// request interceptor
axios.interceptors.request.use(
    config => {
        config.cancelToken = new CancelToken(cancelFn => {
            pendingHandler(config.baseURL + config.url + "&" + config.method, cancelFn);
        });
        return config;
    },
    err => {
        return Promise.reject(err);
    }
);

// response interceptor
axios.interceptors.response.use(
    response => {
        pendingHandler(response.config.url + "&" + response.config.method);
        return response;
    },
    err => {
        pendingArr = [];
        return Promise.reject(err);
    }
);

return debounce(
    axios(config)
    .then(response => {
        // handle response
        resolve(response.data)
    })
    .catch(thrown => {
        if (axios.isCancel(thrown)) {
            console.log("Request canceled", thrown.message);
        } else {
            let { response, request, message } = thrown;
            reject(message);
        }
    }),
    500,
    true
);


// debounce.js
export function debounce(func, wait, immediate) {
    var timeout, args, context, timestamp, result;
    if (null == wait) wait = 100;

    function later() {
        var last = Date.now() - timestamp;

        if (last < wait && last >= 0) {
            timeout = setTimeout(later, wait - last);
        } else {
            timeout = null;
            if (!immediate) {
                result = func.apply(context, args);
                context = args = null;
            }
        }
    }

    var debounced = function() {
        context = this;
        args = arguments;
        timestamp = Date.now();
        var callNow = immediate && !timeout;
        if (!timeout) timeout = setTimeout(later, wait);
        if (callNow) {
            result = func.apply(context, args);
            context = args = null;
        }

        return result;
    };

    debounced.clear = function() {
        if (timeout) {
            clearTimeout(timeout);
            timeout = null;
        }
    };

    debounced.flush = function() {
        if (timeout) {
            result = func.apply(context, args);
            context = args = null;

            clearTimeout(timeout);
            timeout = null;
        }
    };

    return debounced;
}