Vue:Axios前端拦截器

需求描述

    限制用户多次点击按钮,频繁地发送同一个请求,影响页面渲染效果,降低前端的无效接口请求操作(其中涉及到Map、Array、Promise的一些基本操作)。

解决方案

    由于所接触的是Vue项目,项目中使用的接口请求工具为axios(点击此处,查看官网),因此,采用编写前端拦截器的方式来对除第一次之外的——多个处于pending等待状态的同一个无效请求进行过滤,即:只有首次发送的请求会被正常处理,后续的会被直接过滤掉。

基本思路

    使用一个Map集合对象,保存用户发送的每个请求。Map中每一个元素的requestKey唯一标识值由请求的method、url和data参数构成。
    axios拦截器分别为:请求拦截器和响应拦截器,其中,
        ①请求拦截器:在进行接口数据请求时,判断是否已经有相同的请求在执行(Map集合中是否存在由requestKey标识的请求对象),如果有,就直接取消掉当前一次请求;如果没有,则正常执行。
        ②响应拦截器:在正常执行完毕一次接口请求时,就再次获取该请求的requestKey标识值,并根据requestKey标识值从Map集合中移除,以确保下一次接口请求的正常执行。

代码编写

核心代码

//记录处理pending状态的Axios请求对象
    var pendingRequestMap = new Map();
    //拦截器配置
    //1-请求拦截器配置
    axios.interceptors.request.use(function (config) {
        console.warn("请求拦截器...");
        //校验-method|url|data
        let requestKey = `${config.method}-${config.url}-${config.data}`;//创建request请求key
        let cancelFunction = undefined;
        config.requestKey = requestKey;//挂载requestKey到config对象上
        //获取axios取消请求回调函数
        config.cancelToken = new axios.CancelToken((cancel)=>{
            cancelFunction = cancel;
        });//创建cancelToken
        console.log(config);
        //判断当前pendingRequestMap中是否存在当前requestKey
        if(pendingRequestMap.has(requestKey)){
            //执行请求拦截-取消当前一次的请求
            cancelFunction();
        }else {
            //保存当前一次的请求
            pendingRequestMap.set(requestKey,config);
        }
        return Promise.resolve(config);//改变config状态为resolved
    },function (error) {
        return Promise.reject(error);
    });
    //2-响应拦截器配置
    axios.interceptors.response.use(function (response) {
        console.warn("响应拦截器...");
        let requestKey =  response.config.requestKey ;//获取当前请求的Key值
        //如果执行成功-根据key值,从pendingRequestMap中移除当前请求config
        pendingRequestMap.delete(requestKey);
        return Promise.resolve(response);//改变响应结果状态为resolved
    },function (error) {
        return Promise.reject(error);//改变响应结果状态为rejected
    });

完整代码

    以示例demo的形式给出。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>AxiosTest</title>
    <script src="./axios/axios.min.js"></script>
</head>
<body>
    <button id="sendAjax">发送请求</button>
</body>
<script>
    //记录处理pending状态的Axios请求对象
    var pendingRequestMap = new Map();
    //拦截器配置
    //1-请求拦截器配置
    axios.interceptors.request.use(function (config) {
        console.warn("请求拦截器...");
        //校验-method|url|data
        let requestKey = `${config.method}-${config.url}-${config.data}`;//创建request请求key
        let cancelFunction = undefined;
        config.requestKey = requestKey;//挂载requestKey到config对象上
        //获取axios取消请求回调函数
        config.cancelToken = new axios.CancelToken((cancel)=>{
            cancelFunction = cancel;
        });//创建cancelToken
        console.log(config);
        //判断当前pendingRequestMap中是否存在当前requestKey
        if(pendingRequestMap.has(requestKey)){
            //执行请求拦截-取消当前一次的请求
            cancelFunction();
        }else {
            //保存当前一次的请求
            pendingRequestMap.set(requestKey,config);
        }
        return Promise.resolve(config);//改变config状态为resolved
    },function (error) {
        return Promise.reject(error);
    });
    //2-响应拦截器配置
    axios.interceptors.response.use(function (response) {
        console.warn("响应拦截器...");
        let requestKey =  response.config.requestKey ;//获取当前请求的Key值
        //如果执行成功-根据key值,从pendingRequestMap中移除当前请求config
        pendingRequestMap.delete(requestKey);
        return Promise.resolve(response);//改变响应结果状态为resolved
    },function (error) {
        return Promise.reject(error);//改变响应结果状态为rejected
    });

    //事件注册-发送Axios请求
    var btn = document.getElementById("sendAjax");
    btn.addEventListener("click",function (ev) {
        axios({
            method: 'get',
            url: '/shqrpweb/QueryShort/loadChangzhu/test1',
            data: {
                code:"310101"
            }
        }).then(function (result) {
            console.log(result)
        });
    });


</script>
</html>

案例翻转

    上述代码是对同一个接口的多次请求进行过滤,只保留第一次请求的实现。那么,如果指向保留最后一次请求,而取消掉前几次的请求呢?示例代码如下,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>AxiosTest</title>
    <script src="./axios/axios.min.js"></script>
</head>
<body>
    <button id="sendAjax">发送请求</button>
</body>
<script>
    //拦截器配置
    //记录已经发起的所有请求
    var requestPool = new Array();
    //1-请求拦截器配置
    axios.interceptors.request.use(function (config) {
        console.warn("请求拦截器...");
        //校验-method|url|data
        let requestKey = `${config.method}-${config.url}-${config.data}`;//创建request请求key
        if(requestPool&&requestPool.length>0){
            //先判断是否存在相同的请求
            requestPool.forEach((e,index)=>{
                if(e['key'] === requestKey){
                    e['value'].cancel();//存在相同的请求-执行取消操作
                    delete requestPool[index];//从请求池中移除对应的请求
                }
            });
            requestPool = requestPool.filter(item=>typeof  item !== "undefined");//过滤掉空白元素
        }
        config.requestKey = requestKey; //挂载requestKey到config上
        //将取消请求的cancelToken挂载到config实例上
        console.log(config);
        config.cancelToken = new axios.CancelToken((cancel)=>{
            config.cancel = cancel;
        });//创建cancelToken
        //将当前请求添加到请求池中
        requestPool.push({
            key:requestKey,
            value:config,
        });
        //将当前config状态转换为resolved
        return Promise.resolve(config);
    },function (error) {
        return Promise.reject(error);
    });

    //2-响应拦截器配置
    axios.interceptors.response.use(function (response) {
        console.warn("响应拦截器...");
        let requestKey =  response.config.requestKey ;//获取当前请求的Key值
        //如果执行成功-根据key值,从请求池requestPool中移除当前请求config
        requestPool = requestPool.filter(item=>item['key']===requestKey);
        console.log(requestPool);
        return Promise.resolve(response);//改变响应结果状态为resocancelTokelved
    },function (error) {
        return Promise.reject(error);//改变响应结果状态为rejected
    });

    //事件注册-发送Axios请求
    var btn = document.getElementById("sendAjax");
    btn.addEventListener("click",function (ev) {
        axios({
            method: 'get',
            url: '/shqrpweb/QueryShort/loadChangzhu/test1',
            data: {
                code:"310101"
            }
        }).then(function (result) {
            console.log(result)
        });
    });
</script>
</html>
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是席木木啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值