我的编程空间,编程开发者的网络收藏夹
学习永远不晚

web开发中如何优雅的解决"重复请求"问题

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

web开发中如何优雅的解决"重复请求"问题

前言

在我们web开发过程中,很多地方需要我们取消重复的请求。但是哪种场合需要我们取消呢?我们如何取消呢?带着这些问题我们阅读本文。

阅读完本文,你将了解以下内容:

需要取消重复请求的场景

我们如何取消重复请求

axios如何取消重复的请求

封装axios

如何给开源的项目提供源码

如何在本地调试npm包

提出问题

最近做的项目中,用的用户经常遇到这样的问题:

  • 用户频繁切换筛选条件去请求数据,初次的筛选条件数据量大。用的时间比较多。后面的筛选条件的数据量小。导致后面请求的数据先返回。内容先显示在页面上。但是等一段时间,初次(或者前面)的请求数据返回了, 会覆盖后面的请求的数据。这就导致了筛选条件和内容不一致的情况。
  • 用户点击了一次提交按钮,接口没有很快响应,导致页面没办法做逻辑语句判断的提示。用户觉得可能没提交上,便会快速又点了按钮几次。如果后端没有去重的判断,就会导致数据中有很多条重复的数据。

这些问题给用户的体验是很不友好的。那么取消无用的请求是很有必要的。

解决思路

我们用的请求库是axios。那么我们可以在请求的时候拦截请求判断当前的请求是否重复,如果重复我们就取消当前的请求。大致的实现过程如下:

我们把目前处于pending的请求存储(假如我们放在一个数组)起来。每个请求发送之前我们都要判断当前这个请求是否已经存在于这个数组。如果存在,说明请求重复了,我们就在数组中找到重复的请求并且取消。如果不存在,说明这个请求不是重复的,正常发送并且把这个请求api添加在数据中,等请求结束之后删除数组中的这个api。

我们这个解决思路有了,但是axios如何取消请求的呢?我们先来了解下

axios 如何取消请求

查看axios文档发现axios提供了两种取消请求的方法(http://www.axios-js.com/zh-cn/docs/#%E5%8F%96%E6%B6%88)

第一种方法

通过axios.CancelToken.source生成取消令牌token和取消方法cancel

const CancelToken = axios.CancelToken;
const source = CancelToken.source();
axios.get('/user/12345', {
  cancelToken: source.token
}).catch(function(thrown) {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
    // 处理错误
  }
});
axios.post('/user/12345', {
  name: 'new name'
}, {
  cancelToken: source.token
})
// 取消请求 (消息参数是可选的)
source.cancel('Operation canceled by the user.');

第二种方式

通过传递一个 executor 函数到 CancelToken 的构造函数来创建 cancel token

const CancelToken = axios.CancelToken;
let cancel;
axios.get('/user/12345', {
  cancelToken: new CancelToken(function executor(c) {
    // executor 函数接收一个 cancel 函数作为参数
    cancel = c;
  })
});
// 取消请求
cancel();

封装axios

解决取消请求的思路有了,取消请求的办法也有了,那么剩下的就是封装了

由于同事之前已经封装了axios——very-axios(https://github.com/verymuch/very-axios) (基于 axios 进行二次封装,更简单、更统一地使用 axios)。那么我们就这个基础上提一个pr吧。那么从现在开始我们就一步一步的来实现,这个过程包含了【如何给开源的项目贡献代码】【如何在本地调试npm】如果已经了解的同学可以直接略过。

准备工作

由于同事已经封装了axios并且已经开源了。那么我贡献代码的方式主要有两种:

  • 代码仓库的管理者给我们添加这个仓库的写入权限,如果这样,我们就可以直接提push。
  • 如果我们没有权限(大多数情况)。我们使用经典的fork & pull request 的方式来提交代码。

我们采用的第二种方式。我们去 very-axios(https://github.com/verymuch/very-axios) 把代码fork到自己的仓库(如果你还没有自己的github,需要自己注册下哦)。

那么你回到自己的github仓库下面就会看有一个一摸一样的项目

那么我们现在就可以git clone这个仓库的代码到本地,新建branch进行开发,就比如我新建了一个这样的branch:

现在已经有本地的代码了,但是我们如何本地化调试npm包呢?那就需要npm link 了

首先在我们要修改的npm 包中npm link:

之后我们会得到

/Users/shuliqi/.nvm/versions/node/v12.17.0/lib/node_modules/very-axios -> /Users/shuliqi/study/axios/very-axios

这意思就是我们把very-axios链接到全局的node_modules

然后我们进入我们my-project-of-axios 目录下面执行npm link very-axios 如图:

这意思就是very-axios被安装在my-project-of-axios 下面了。very-axios的修改都会同步到my-project-of-axios。就实现本地测试了。

我们在my-project-of-axios中的HelloWorld.vue文件中做列子。

如果这里看的不是很懂的同学可以看看这两篇文章:如何在本地调试npm包(https://github.com/allenGKC/Blog/issues/13)。如何使用 GitHub Flow 给开源项目贡献代码(https://juejin.im/post/6844903636863041550)

开始封装

准备工作完成了, 那我们开始封装的事情。根据我们之前的思路。我们采用axios 如何取消请求的第一种方式。

声明一个Map。用来存储每个请求的 标识 和 取消的函数

// 存储每个请求的标识和取消的函数
this.pendingAjax = new Map();

自定一个字段来让用户自己决定是否需要取消重复的请求

// 是否取消重复的请求
cancelDuplicated = false,

自定一个字段来让用户是否有全局的统一的设置重复标识的函数。如果没有设置全局的统一的函数,则默认是请求的method 和url作为重复的标识

// 生成重复标识的方式
duplicatedKeyFn,
this.duplicatedKeyFn = isFunction(duplicatedKeyFn) ? duplicatedKeyFn : (config) => `${config.method}${config.url}`;

添加请求


addPendingAjax(config) {
  // 是否需要取消重复的请求
  if (!this.cancelDuplicated) return
  const veryConfig = config.veryConfig || {};
  const duplicatedKey = JSON.stringify({
    duplicatedKey: veryConfig.duplicatedKey || this.duplicatedKeyFn(config),
    type: REQUEST_TYPE.DUPLICATED_REQUEST,
  });
  config.cancelToken = config.cancelToken || new axios.CancelToken((cancel) => {
    // 如果pendingAjax中不存在当前请求,添加进去
    if (duplicatedKey && !this.pendingAjax.has(duplicatedKey)) {
      this.pendingAjax.set(duplicatedKey, cancel);
    }
  });
}

这里面我们可以使用duplicatedKey字段来让用户对单一请求自定义重复的标识。或者可以使用一个函数duplicatedKeyFn统一的让用户自定义重复的标识

删除请求


  removePendingAjax(config) {
    // 是否需要取消重复的请求
    if (!this.cancelDuplicated) return
    const veryConfig = config.veryConfig || {};
    const duplicatedKey = JSON.stringify({
      duplicatedKey: veryConfig.duplicatedKey || this.duplicatedKeyFn(config),
      type: REQUEST_TYPE.DUPLICATED_REQUEST,
    });
    // 如果pendingAjax中存在当前请求, 取消当前请求并将其删除
    if (duplicatedKey && this.pendingAjax.has(duplicatedKey)) {
      const cancel = this.pendingAjax.get(duplicatedKey);
      cancel(duplicatedKey);
      this.pendingAjax.delete(duplicatedKey);
    }
  }

封装好了, 我们在哪里使用呢?肯定是在请求开始之前和请求完成之后使用。

在请求之前

// 拦截请求
this.axios.interceptors.request.use((config) => {
  // 在请求开始之前检查先前的请求
  this.removePendingAjax(config);
  // 将当前请求添加到pendingAjax
  this.addPendingAjax(config);
  // ...
});

在请求完成之后去掉该请求

// 拦截响应
this.axios.interceptors.response.use(response => {
  removePending(response)
  return response
}, error => {
  // ...
})

到现在已经完成了该有的功能, 但是取消请求的错误我们不该返回给用户。所以:

(err) => {
// 类型是否为重复请求
let isDuplicatedType;
try {
  const errorType = (JSON.parse(error.message) || {}).type
  isDuplicatedType = errorType === REQUEST_TYPE.DUPLICATED_REQUEST;
} catch (error) {
  isDuplicatedType = false
}
if (isDuplicatedType) return;
}

我们在请求完成之后的err里面做一个判断,判断如果当前请求是取消的类型,我们就不返回给用户错误的提示信息。

总结

至此,完成了我们的封装。完成的pr地址:(https://github.com/verymuch/very-axios/pull/1)。本文测试npm包的项目地址:(https://github.com/shuliqi/my-project-of-axios)

到此这篇关于web开发中如何优雅的解决"重复请求"问题的文章就介绍到这了,更多相关axios取消重复请求内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

web开发中如何优雅的解决"重复请求"问题

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

在Go语言中如何解决并发网络请求的请求路由和请求过滤问题?

在Go语言中如何解决并发网络请求的请求路由和请求过滤问题?在Go语言中,通过使用goroutine和channel的方式可以很方便地实现并发网络请求。但是在实际应用中,我们经常会遇到请求路由和请求过滤的问题,即不同的请求需要调用不同的处理函
2023-10-22

在Go语言中如何解决并发网络请求的请求连接池和连接复用问题?

在Go语言中如何解决并发网络请求的请求连接池和连接复用问题?由于Go语言天生支持并发,因此在进行网络请求时,我们往往需要处理大量的并发请求。为了提高性能和减少资源消耗,我们需要使用连接池来复用网络连接。在Go语言中,可以使用sync.Poo
2023-10-22

在Go语言中如何解决并发网络请求的请求错误重试和容错处理问题?

在Go语言中如何解决并发网络请求的请求错误重试和容错处理问题?随着互联网的高速发展,网络请求已经成为了日常开发中不可或缺的一部分。然而,网络请求并不总是成功的,可能会遇到各种错误。在并发请求中,这些错误很可能会导致整个程序的崩溃,因此我们需
2023-10-22

如何解决Go语言中的并发任务的优雅停机和平滑重启问题?

如何解决Go语言中的并发任务的优雅停机和平滑重启问题?在Go语言中,我们经常会遇到需要处理并发任务的情况。然而,并发任务的停机和重启可能会造成资源泄漏或数据丢失等问题。为了解决这些问题,我们需要采用一些优雅的停机和平滑重启的方法。一、优雅停
2023-10-22

Go语言中如何解决并发请求的错误处理问题?

Go语言中如何解决并发请求的错误处理问题?在开发并发应用时,我们时常需要发送多个并发请求以提高程序的并发性能。然而,当其中一个请求发生错误时,如何有效地捕获和处理这些错误变得非常重要。Go语言提供了一些技术和模式来解决并发请求的错误处理问题
2023-10-22

在Go语言中如何解决并发网络请求的请求身份认证和访问授权问题?

在Go语言中如何解决并发网络请求的请求身份认证和访问授权问题?随着互联网的快速发展,越来越多的应用需要进行网络请求,涉及到用户身份认证和访问授权问题。如何在Go语言中解决并发网络请求的请求身份认证和访问授权问题,成为了开发者们面临的一项重要
2023-10-22

在Go语言中如何解决并发网络请求的请求流量控制和限流问题

在Go语言中,可以使用一些库或模式来解决并发网络请求的请求流量控制和限流问题。以下是一些常见的解决方案:1. 使用goroutine池:可以创建一个固定大小的goroutine池,限制同时进行的最大并发请求数量。可以使用`sync.Wait
2023-10-09

在Go语言中如何解决并发网络请求的请求流量控制和限流问题?

在Go语言中如何解决并发网络请求的请求流量控制和限流问题?在现代的网络应用中,大量的并发网络请求是非常常见的情况。对于服务器来说,如果无法有效地控制和限制这些请求的流量,可能会导致服务器负载过高,甚至崩溃。因此,在Go语言中如何解决并发网络
2023-10-22

在Go语言中如何解决并发网络请求的请求合并和批量处理问题?

在Go语言中如何解决并发网络请求的请求合并和批量处理问题?在现代互联网应用中,网络请求已经成为了不可或缺的一部分,而对于高并发的情况下,如何有效地管理和处理大量的网络请求成了一个亟待解决的问题。为了提高请求的效率和减少网络开销,我们常常需要
2023-10-22

在Go语言中如何解决并发网络请求的请求认证和授权处理问题?

在Go语言中如何解决并发网络请求的请求认证和授权处理问题?随着互联网的高速发展,网络请求在我们的日常开发中扮演着非常重要的角色。然而,随着系统规模的扩大和并发量的增加,请求认证和授权问题也逐渐变得复杂起来。在这篇文章中,我们将探讨在Go语言
2023-10-22

在Go语言中如何解决并发网络请求的请求缓存和缓存更新问题

在Go语言中,可以使用sync.Map来实现请求缓存和缓存更新的问题。首先,我们可以创建一个全局的sync.Map来作为缓存,用于存储已经请求过的URL和对应的响应数据。sync.Map是Go语言提供的并发安全的map。```govar c
2023-10-09

在Go语言中如何解决并发网络请求的请求缓存和缓存更新问题?

标题:Go语言中的并发网络请求的请求缓存和缓存更新问题解决方案引言:在现代程序开发中,网络请求是非常常见的操作,而并发请求更是提高程序性能和响应速度的关键。然而,在并发网络请求中,往往会面临请求重复发送、数据不一致等问题。本文将介绍如何在G
2023-10-22

在Go语言中如何解决并发网络请求的请求限速和流量控制问题?

在Go语言中如何解决并发网络请求的请求限速和流量控制问题?Go语言是一门非常适合进行并发编程的语言,它提供了丰富的并发原语和工具,可以方便地实现请求限速和流量控制。本文将介绍如何使用Go语言来解决并发网络请求的请求限速和流量控制问题,并提供
2023-10-22

在Go语言中如何解决并发网络请求的请求参数校验和合法性问题?

在Go语言中进行并发网络请求时,我们经常需要对请求参数进行校验和合法性检查。本文将介绍如何使用Go语言的并发特性来解决这些问题,并提供具体的代码示例。首先,我们需要使用Go语言的协程来同时发送多个网络请求。Go语言提供了goroutine来
2023-10-22

如何解决PHP开发中的性能瓶颈和优化问题

在PHP开发过程中,性能瓶颈和优化问题是我们经常面对的挑战。一个高效的PHP应用程序可以提升用户体验,减少服务器负载,并节省成本。本文将探讨一些常见的性能瓶颈问题,并提供一些解决方案和代码示例。一、数据库查询优化数据库查询是PHP应用程序中
2023-10-21

在Go语言中如何解决并发网络请求的请求服务降级和异常处理问题?

在Go语言中如何解决并发网络请求的请求服务降级和异常处理问题?随着互联网的快速发展,越来越多的应用需要进行并发网络请求。然而,在高并发的情况下,网络请求可能会导致超时、阻塞等问题,从而影响到整个系统的稳定性和可靠性。面对这个问题,我们可以使
2023-10-22

在Go语言中如何解决并发网络请求的请求负载均衡和故障转移问题?

在Go语言中如何解决并发网络请求的请求负载均衡和故障转移问题?随着现代互联网应用的复杂性不断增加,大量的网络请求往往需要通过多个服务节点来处理。为了提高系统的可用性和性能,请求需要通过负载均衡来分发到不同的节点上。同时,在节点发生故障时,请
2023-10-22

编程热搜

目录