Vue+Axios:使用拦截器来取消多次重复的请求

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

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

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

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

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

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

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

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

这篇博客主要解决问题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不匹配从而无法拦截。

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

原文地址:https://www.cnblogs.com/linbudu/p/11259070.html

时间: 2024-10-05 06:16:40

Vue+Axios:使用拦截器来取消多次重复的请求的相关文章

Axios使用拦截器全局处理请求重试

Axios拦截器 Axios提供了拦截器的接口,让我们能够全局处理请求和响应.Axios拦截器会在Promise的then和catch调用前拦截到. 请求拦截示例 axios.interceptors.request.use(function (config) { // 在发起请求请做一些业务处理 return config; }, function (error) { // 对请求失败做处理 return Promise.reject(error); }); 响应拦截示例 axios.inte

拦截器springmvc防止表单重复提交【2】

[参考博客:http://my.oschina.net/mushui/blog/143397] 原理:在新建页面中Session保存token随机码,当保存时验证,通过后删除,当再次点击保存时由于服务器端的Session中已经不存在了,所有无法验证通过. 1.新建注解: /** * <p> * 防止重复提交注解,用于方法上<br/> * 在新建页面方法上,设置needSaveToken()为true,此时拦截器会在Session中保存一个token, * 同时需要在新建的页面中添加

拦截器springmvc防止表单重复提交【1】

[参考博客:http://www.cnblogs.com/hdwpdx/archive/2016/03/29/5333943.html] springmvc 用拦截器+token防止重复提交 首先,防止用户重复提交有很多种方式,总体分为前端JS限制和后端限制,我个人认为后端限制比较妥当(本着能做到更优秀得理念,舍去了前端JS限制重复提交得想法). 之前没有做过防止用户重复提交,所以直接百度了一大堆,竟然发现基本上可以归为2到3种真正不同实现得代码,文章虽然有很多,不过大部分代码几乎都出自同一人,

细说vue axios登录请求拦截器

当我们在做接口请求时,比如判断登录超时时候,通常是接口返回一个特定的错误码,那如果我们每个接口都去判断一个耗时耗力,这个时候我们可以用拦截器去进行统一的http请求拦截. 1.安装配置axios cnpm install --save axios 我们可以建一个js文件来做这个统一的处理,新建一个axios.js,如下 import axios from 'axios' import { Indicator } from 'mint-ui'; import { Toast } from 'min

vue axios 拦截器

前言 项目中需要验证登录用户身份是否过期,是否有权限进行操作,所以需要根据后台返回不同的状态码进行判断. 第一次使用拦截器,文章中如有不对的地方还请各位大佬帮忙指正谢谢. 正文 axios的拦截器分为请求拦截器和响应拦截器两种.我一般把拦截器写在main.js里. mian.js//axios请求 import Axios from "axios"; Vue.prototype.$axios = Axios; 请求拦截器 axios.interceptors.request.use(

Vue2学习小记-给Vue2路由导航钩子和axios拦截器做个封装

1.写在前面 最近在学习Vue2,遇到有些页面请求数据需要用户登录权限.服务器响应不符预期的问题,但是总不能每个页面都做单独处理吧,于是想到axios提供了拦截器这个好东西,再于是就出现了本文. 2.具体需求 用户鉴权与重定向:使用Vue提供的路由导航钩子 请求数据序列化:使用axios提供的请求拦截器 接口报错信息处理:使用axios提供的响应拦截器 3.简单实现 3.1 路由导航钩子层面鉴权与重定向的封装 路由导航钩子所有配置均在router/index.js,这里是部分代码 import

vue+axios 前端实现的常用拦截

一.路由拦截使用 router.beforeEach((to, from, next) => { if (to.meta.requireAuth) { // 判断该路由是否需要登录权限 if (store.state.token) { // 通过vuex state获取当前的token是否存在 next(); } else { next({ path: '/login', query: {redirect: to.fullPath} // 将跳转的路由path作为参数,登录成功后跳转到该路由 }

axios拦截器使用方法

vue中axios获取后端接口数据有时候需要在请求开始时显示loading,请求结束后隐藏loading,这时候到每次调接口时都写上有点繁琐,有时候还会漏写. 这时候axios的拦截器就起了作用,我们可以在发送所有请求之前和操作服务器响应数据之前对这种情况过滤.定义拦截器如下: import Vue from 'vue' import axios from 'axios' import { Indicator } from 'mint-ui' import { Toast } from 'min

vue+axios 前端实现登录拦截

参考:http://blog.csdn.net/qq673318522/article/details/55506650 登录拦截逻辑 第一步:路由拦截 首先在定义路由的时候就需要多添加一个自定义字段requireAuth,用于判断该路由的访问是否需要登录.如果用户已经登录,则顺利进入路由, 否则就进入登录页面. const routes = [ { path: '/', name: '/', component: Index }, { path: '/repository', name: 'r