axios中取消阻止重复请求(防抖请求) 您所在的位置:网站首页 重复向好友发送请求 axios中取消阻止重复请求(防抖请求)

axios中取消阻止重复请求(防抖请求)

2024-07-13 20:43| 来源: 网络整理| 查看: 265

目录 前言核心——CancelToken实际应用和封装一些小细节

前言

在实际项目中,我们可能需要对请求进行“防抖”处理。这里主要是为了阻止用户在某些情况下短时间内重复点击某个按钮,导致前端向后端重复发送多次请求。这里我列举两种比较常见的实际情况:

PC端 - 用户双击搜索按钮,可能会触发两次搜索请求移动端 - 因移动端没有点击延迟,所以极易造成误操作或多操作,造成请求重发

以上情况有可能在有Loading遮罩时依然发生,所以我们要考虑前端阻止重复请求的方法。

核心——CancelToken

在Axios中取消请求最核心的方法是CanelToken。在官网文档中有写到两种方法使用CancelToken,这里简单粘贴出来,并增加了注释

方法1:

const CancelToken = axios.CancelToken; const source = CancelToken.source(); axios.get('/user/12345', { // 必须对请求进行cancelToken设置 cancelToken: source.token }).catch(function (thrown) { // 如果请求被取消则进入该方法判断 if (axios.isCancel(thrown)) { console.log('Request canceled', thrown.message); } else { // handle error } }); // 取消上面的请求 // source.cancel('messge') message为可选项,必须为String source.cancel('Operation canceled by the user.');

方法2:

const CancelToken = axios.CancelToken; let cancel; axios.get('/user/12345', { // 在options中直接创建一个cancelToken对象 cancelToken: new CancelToken(function executor(c) { cancel = c; }) }); // 取消上面的请求 cancel(); 实际应用和封装

上文已对axios中的核心方法进行了举例,但是在实际中我们往往不会像官网例子中那样使用,更多的是在axios的拦截器中做全局配置管理。这样的话我们需要对上面的代码进行一些改变。

这里说一下我实现的大体思路:

我们需要对所有正在进行中的请求进行缓存。在请求发起前判断缓存列表中该请求是否正在进行,如果有则取消本次请求。在任意请求完成后,需要在缓存列表中删除该次请求,以便可以重新发送该请求

思路说完,我们直接上代码

// 正在进行中的请求列表 let reqList = [] /** * 阻止重复请求 * @param {array} reqList - 请求缓存列表 * @param {string} url - 当前请求地址 * @param {function} cancel - 请求中断函数 * @param {string} errorMessage - 请求中断时需要显示的错误信息 */ const stopRepeatRequest = function (reqList, url, cancel, errorMessage) { const errorMsg = errorMessage || '' for (let i = 0; i cancel(errorMsg) return } } reqList.push(url) } /** * 允许某个请求可以继续进行 * @param {array} reqList 全部请求列表 * @param {string} url 请求地址 */ const allowRequest = function (reqList, url) { for (let i = 0; i reqList.splice(i, 1) break } } } const service = axios.create() // 请求拦截器 service.interceptors.request.use( config => { let cancel // 设置cancelToken对象 config.cancelToken = new axios.CancelToken(function(c) { cancel = c }) // 阻止重复请求。当上个请求未完成时,相同的请求不会进行 stopRepeatRequest(reqList, config.url, cancel, `${config.url} 请求被中断`) return config }, err => Promise.reject(err) ) // 响应拦截器 service.interceptors.response.use( response => { // 增加延迟,相同请求不得在短时间内重复发送 setTimeout(() => { allowRequest(reqList, response.config.url) }, 1000) // ...请求成功后的后续操作 // successHandler(response) }, error => { if (axios.isCancel(thrown)) { console.log(thrown.message); } else { // 增加延迟,相同请求不得在短时间内重复发送 setTimeout(() => { allowRequest(reqList, error.config.url) }, 1000) } // ...请求失败后的后续操作 // errorHandler(error) } ) 一些小细节 为什么没用前文方法2中的代码进行cancelToken设置? axios的文档中有一条备注:

Note: you can cancel several requests with the same cancel token. 你可以使用相同的Token来取消多个请求

所以我不想在每个请求前都new一个新的对象 请务必使用方法2,保证每次cancel都能正确执行。之前方法会导致当出现cancel后,后续请求也会持续cancel

为什么在response中需要增加延迟? 因为不想让用户在极短的时间内重复进行相同请求。 请注意,在response中阻止请求和在request中的阻止请求是两个概念: request中是阻止上个请求 未完成 时又开始了相同的请求 response中是阻止上个请求 完成后 一段时间内不允许相同请求

我能否在cancel时传递一个对象,而不仅仅是message? 以官方提供的接口来看是不可以的,你可以仿照官方源码进行重新封装,或者使用第三方插件,或者使用另一个方法:将对象转换为JSON字符串,然后在需要的地方再转换回来

原文链接:https://blog.csdn.net/harsima/article/details/93717217



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有