zoukankan      html  css  js  c++  java
  • Vue+Axios:使用拦截器来取消多次重复的请求

    -----写在前面-----

    家园的面试项目接近尾声了,剩下一个大模块(响应式布局)和两个小功能(下拉到一定程度获取新的信息、持续监听返回数据,当有更新时在页面上方提示)

    听起来下拉到某个位置获取新信息是不难,但今天就遇到了两个问题:

    1. 下拉过程中会不断发起url相同的请求,可能会有被拉黑的风险,并且影响实际性能。最重要的,在then()方法中会将返回数据稍做处理后添加进组件数据,并且会驱动Vue更新DOM,

    因为用的v-for来填充数据,这样同一条数据就会被渲染两次

    2.ReadHub除了topic栏外,其余四个栏目下拉获取更新数据的api接口地址中的参数是时间戳!!而且返回的数据长度也不同

    这就导致除了topic以外的栏目在获取更新数据后还要和已有的数据进行比对,不能重复,目前的想法是

    在负责更新数据的axios.then()方法中,detail(存储所有数据)转set结构,然后把新返回的数据push进去,再转回数组(也可以不转回去?)

    ⬆⬆⬆⬆⬆这个想法无法执行,因为很神奇的,同样的api接口可能返回两种不同格式的数据

    第0条和第10条的数据是一样的(以此类推...)。而且我暂时没有找到剩下的四个栏目,更新列表发起的请求地址中的时间戳是哪里来的??

    (topic栏目是直接根据未加载时列表最下方的一条数据的order来请求的)

    而且这个时间戳也没有规律啥的...

    这篇博客主要解决问题1,即拦截相同url的axios请求,网上教程是一堆,但好像大家都是从同一份魔改出来的?因此我头皮发麻的想了好久,在思否的提问只有21个浏览...

     

    推荐阅读Axios的中文文档

     

    首先需要明白拦截器的工作原理,axios中内置了两个拦截器,请求拦截器与响应拦截器,分别通过以下两个方法调用

    axios.interceptors.request.use()
    axios.interceptors.response.use()


    拦截器的触发:

    对于单个请求来说,在请求发送后会触发request拦截器进行拦截。

    因此可以有以下思路,建立一个空数组,第一次请求成功发送后将本次请求的url保存起来,下一次再次发送请求,会先在请求拦截器中检验这一请求的url是否在这个数组中被保存了,

    如果是,则取消本次请求(AXIOS提供了cancelToken来取消请求,详见后文)。

    如果有需要的话,在响应拦截器中,在成功返回响应后将本次请求的url从数组中去掉,以便后续的使用,这一情况适用于防止用户多次点击发送重复请求?即这个接口后面还有可能用到

            let pending = []; //声明一个数组用于存储每个请求的取消函数和axios标识
                let cancelToken = axios.CancelToken;
                let removePending = (config) => {
                    // console.log(config);
                    for(let i in pending){
                        if(pending[i].url === axios.defaults.baseURL+config.url) { //在当前请求在数组中存在时执行取消函数
                            pending[i].f(); //执行取消操作
                            //pending.splice(i, 1); 根据具体情况决定是否在这里就把pending去掉
                            console.log(pending[i].url);
                        }
                    }
                }

    请求拦截器与响应拦截器:

    axios.interceptors.request.use(config => {
                    removePending(config); //在一个axios发送前执行一下判定操作,在removePending中执行取消操作
                    // console.log(config.url);
                    config.cancelToken = new cancelToken(function executor(c){//本次axios请求的配置添加cancelToken
                    pending.push({
                        // url: config.url,
                        url: axios.defaults.baseURL+config.url,
                        f:c
                    }); 
                    // console.log(axios.defaults.baseURL+config.url);
                    //将本次的url添加到pending中,因此对于某个url第一次发起的请求不会被取消,因为还没有配置取消函数
                });
                    return Promise.resolve(config);
                }, error => {
                    return Promise.reject(error)
                })
                axios.interceptors.response.use(data => { 
                    // removePending(data.config); //在一个axios响应后再执行一下取消操作,把已经完成的请求从pending中移除
                    // console.log(data.config);//如果返回undefined说明被拦截了
                    return Promise.resolve(data)
                    
                    }, error => {
                    //加载失败
                    return {'data':{}}
                    })

    这里的详解见上面的axios中文文档哈,如果懒得看只要知道这里的c是new cancelToken构造器生成的取消函数就行。

     注意这里两行不同的url,使用上面一行会导致无法拦截,因为项目前面手动设置了axios.defaults.baseURL,导致这里传入的url如果不加上baseURL,就只会是/topic?lastCursor=xxxxxx&pageSize=20,

    但在pending数组⬇中的则是完整的url,就会导致url不匹配从而无法拦截。

    建议把这里注释掉的控制台打印代码好好运行几遍~

  • 相关阅读:
    个人冲刺二(7)
    个人冲刺二(6)
    个人冲刺二(5)
    个人冲刺二(4)
    对称二叉树 · symmetric binary tree
    108 Convert Sorted Array to Binary Search Tree数组变成高度平衡的二叉树
    530.Minimum Absolute Difference in BST 二叉搜索树中的最小差的绝对值
    pp 集成工程师 mism师兄问一问
    17. Merge Two Binary Trees 融合二叉树
    270. Closest Binary Search Tree Value 二叉搜索树中,距离目标值最近的节点
  • 原文地址:https://www.cnblogs.com/linbudu/p/11259070.html
Copyright © 2011-2022 走看看