项目中如何使用axios过滤多次重复请求详解

 更新时间:2021年07月07日 11:26:13   作者:峰峰会很好  
在项目开发中经常需要处理重复点击导致多次调用接口的问题,这篇文章主要介绍了项目中如何使用axios过滤多次重复请求的相关资料,需要的朋友可以参考下

一、前言:

我们在web应用开发过程当中,经常会遇到一个时刻发起了多个请求的场景

这个情况下,我们通常的做法有两种:

  • 可以在请求时show一个loading,阻止用户操作。
  • 或者人为加个变量,做一个请求的节流

我们的项目中,目前大部分情况也是采用以上两种方式做的。今天来介绍一个新的方式。

二、CancelToken类

我们之前实例化一个Promise,这个对象是否成功与否,是无法在函数外部决定的,这里边使用要用到一个小窍门,可以让一个promise 和resolve分离。任何时机都可以触发resolve:

  // 一个promise
  let resolvePromise
  let p = new Promise((resolve, reject) => {
    resolvePromise = resolve
  })
  // 这样在外部执行
  resolvePromise()

ok,有了这个前提,我们需要借助axios.CancelToken这个类。

这个类相当于在每次请求的时候开启另一个promise和当前的请求形成一个promise.race(请求p1,取消请求p2),在promise中的resolve方法赋值给了一个外部的变量去接收。我们可以根据需求,人为决定是否取消前次请求。其实这就类似,原来我们写fetch封装接口超时的Promise.race类似。

cancelToken中也提供了相应的static方法source用来生成一个cancelToken和一个cancel方法其实就是这个promise的一个resolve。

    CancelToken.source = function source() {
    var cancel;
    // 
    var token = new CancelToken(function executor(c) {
        cancel = c;
    });
    return {
        token: token,
        cancel: cancel,
    };

根据我们常用的的缓存方式,我们可以声明一个map来存储每次请求的url,同时存储对应的cancel方法。

    // 声明一个全局map
    const pendingHttp = new Map()
    // axios中内置的CancelToken类
    const CancelToken = axios.CancelToken
       
    function addApi (config) {
      config.cancelToken = new CancelToken((cancel) => {
        const url = config.url
        console.log(pendingHttp)
        if (!pendingHttp.has(url)) {
          pendingHttp.set(url, cancel)
        }
      })
    }

    function cancelApi (config) {
      const url = config.url
      if (pendingHttp.has(url)) { // 如果在 pending 中存在当前请求标识,需要取消当前请求,并且移除
        const cancel = pendingHttp.get(url)
        cancel(url + '取消了')
        pendingHttp.delete(url) // 清空当前url的缓存
      }
    }
  • 要特殊注意,要想取消掉一个请求,需要在config上添加cancelToken这个属性赋值为CancelToken的实例。否则cancel不掉。

就像操作定时器一样,要先尝试取消上一次,然后再开启下一次

    httpService.interceptors.request.use(config => {

      cancelApi(config)
      addApi(config)
      
      // 本地调试的时候,是跨域的情况,加请求头会有限制(此处是项目代码无关紧要)
      const { headers = {} } = config; const { globalObj = {} } = window
      Object.assign(headers, globalObj, { from })
      
      return config
    }, error => {
      console.log(error)
      return Promise.reject(error)
    })

然后还有一种可能性,第一次请求已经返回了,又发起了相同的一次请求,所以在response里边也要cancelApi一下。

    httpService.interceptors.response.use(
      response => {
        cancelApi(response.config)
        sentryCatchApi(response)
      },
      error => {
        // 请求超时
        if (error.message.includes('timeout')) { // 判断请求异常信息中是否含有超时timeout字符串
          Toast.error({ text: '网页请求超时,请刷新重试~' })
        }
        sentryCatchApi(error)
        return Promise.reject(error)
      }
    )

我们需要注意一点,cancel其实就是resolve,我们cancel执行时候传入的参数,会最终在response的error回调中,作为参数返回,这样我们的捕捉错误的方法可能会有报错。

    // 假设我们的error方法是这样封装的。 来看一下sentryCatchApi
    error => {
      sentryCatchApi(error)
      return Promise.reject(error)
    }
  // 由于这个方法需要接收一个对象,但是我们cancel取消请求的情况下,返回的是一个字符串,这时就报错了。
  function sentryCatchApi (res) {
      try {
        res = res || {}
        const resData = res.data || {}
        Sentry.captureException(JSON.stringify(resData))
        console.log(`
          获取数据失败:
          请在浏览器中打开进入 webview的地址,并粘贴出来,便于问题排查
          :接口相关信息:
          接口地址:${res.config.url},
          接口返回值:code:${resData.code},
          message:${resData.message},
          data:${JSON.stringify(resData.data)}
        `)
      } catch (err) {
        console.error(err)
      }
    }

需要使用isCancel这个api

   error => {
    if (axios.isCancel(error)) return console.log('请求被取消了', error.message)
    sentryCatchApi(error)
    return Promise.reject(error)
  }

最终效果

控制台也没有任何报错啦。(后续完善到项目中)

总结

到此这篇关于项目中如何使用axios过滤多次重复请求的文章就介绍到这了,更多相关axios过滤多次重复请求内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 详解el Cascader懒加载数据回显示例

    详解el Cascader懒加载数据回显示例

    这篇文章主要为大家介绍了详解el Cascader懒加载数据回显示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • vue基础之使用get、post、jsonp实现交互功能示例

    vue基础之使用get、post、jsonp实现交互功能示例

    这篇文章主要介绍了vue基础之使用get、post、jsonp实现交互功能,结合实例形式分析了vue.js中get、post及jsonp针对本地文件、网络接口实现交互功能相关操作技巧,需要的朋友可以参考下
    2019-03-03
  • Vue项目中接口调用的详细讲解

    Vue项目中接口调用的详细讲解

    应公司需求,接口需要对接vue,记录一下碰到的问题,下面这篇文章主要给大家介绍了关于Vue项目中接口调用的详细讲解,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-07-07
  • Vue3使用Proxy构建高效响应式数据的示例代码

    Vue3使用Proxy构建高效响应式数据的示例代码

    在 Vue 3 中,Proxy 主要用于 拦截对象的基本操作,包括 属性读取(get)、修改(set)、删除(deleteProperty) 等,本文给大家介绍了Vue3使用Proxy构建高效响应式数据的操作教程,需要的朋友可以参考下
    2025-03-03
  • Vue2中Element DatePicker组件设置默认日期及控制日期范围

    Vue2中Element DatePicker组件设置默认日期及控制日期范围

    后台项目想使用时间选择器选择一段时间进行数据筛选,所以下面这篇文章主要给大家介绍了关于Vue2中Element DatePicker组件设置默认日期及控制日期范围的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-11-11
  • watch里面的deep和immediate作用及说明

    watch里面的deep和immediate作用及说明

    这篇文章主要介绍了watch里面的deep和immediate作用及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • vue项目实现图片上传功能

    vue项目实现图片上传功能

    这篇文章主要为大家详细介绍了vue项目实现图片上传功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-12-12
  • Vue中的父子组件传值及传方法

    Vue中的父子组件传值及传方法

    这篇文章主要介绍了Vue中的父子组件传值及传方法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • vue异步加载高德地图的实现

    vue异步加载高德地图的实现

    这篇文章主要介绍了vue异步加载高德地图的实现,详细的介绍了异步加载的实现方法。小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-06-06
  • vue实现token登录验证的完整实例

    vue实现token登录验证的完整实例

    最近公司新启动了个项目,用的是vue框架在做,下面这篇文章主要给大家介绍了关于vue实现token登录验证的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-04-04

最新评论