不到50行代码实现一个能对请求并发数做限制的通用RequestDecorator

使用场景

在开发中,我们可能会遇到一些对异步请求数做并发量限制的场景,比如说微信小程序的request并发最多为5个,又或者我们需要做一些批量处理的工作,可是我们又不想同时对服务器发出太多请求(可能会对服务器造成比较大的压力)。这个时候我们就可以对请求并发数进行限制,并且使用排队机制让请求有序的发送出去。

介绍

那么,接下来我们就来讲一下如何实现一个通用的能对请求并发数进行限制的RequestDecorator。我们先来介绍一下它的功能:

  1. 既然涉及到并发数限制,它就肯定允许用户传入最大并发数限制参数:maxLimit
  2. 既然是一个通用的RequestDecorator,那么它应该允许使用者传入其喜欢的异步api(比如ajax, fetch, axios等)。
  3. 为了方便起见,也为了开发便利性,被RequestDecorator封装后的request请求结果都返回一个promise。
  4. 由于使用者传入的异步api不一定是promise类型的,也可能是callback类型的,因此我们提供用户一个needChange2Promise参数,使用者若传入的是callback类型的api,它可以通过将这个参数设置为true来将callback类型转化为promise类型。

分析完功能后,接下来我们就来实现这个东西:

实现

具体代码如下,每一步我基本都做了注释,相信大家能看懂。

const pify = require('pify');class RequestDecorator {constructor ({maxLimit = 5,requestApi,needChange2Promise,}) {// 最大并发量this.maxLimit = maxLimit;// 请求队列,若当前请求并发量已经超过maxLimit,则将该请求加入到请求队列中this.requestQueue = [];// 当前并发量数目this.currentConcurrent = 0;// 使用者定义的请求api,若用户传入needChange2Promise为true,则将用户的callback类api使用pify这个库将其转化为promise类的。this.requestApi = needChange2Promise ? pify(requestApi) : requestApi;}// 发起请求apiasync request(...args) {// 若当前请求数并发量超过最大并发量限制,则将其阻断在这里。// startBlocking会返回一个promise,并将该promise的resolve函数放在this.requestQueue队列里。这样的话,除非这个promise被resolve,否则不会继续向下执行。// 当之前发出的请求结果回来/请求失败的时候,则将当前并发量-1,并且调用this.next函数执行队列中的请求// 当调用next函数的时候,会从this.requestQueue队列里取出队首的resolve函数并且执行。这样,对应的请求则可以继续向下执行。if (this.currentConcurrent >= this.maxLimit) {await this.startBlocking();}try {this.currentConcurrent  ;const result = await this.requestApi(...args);return Promise.resolve(result);} catch (err) {return Promise.reject(err);} finally {console.log('当前并发数:', this.currentConcurrent);this.currentConcurrent--;this.next();}}// 新建一个promise,并且将该reolsve函数放入到requestQueue队列里。// 当调用next函数的时候,会从队列里取出一个resolve函数并执行。startBlocking() {let _resolve;let promise2 = new Promise((resolve, reject) => _resolve = resolve);this.requestQueue.push(_resolve);return promise2;}// 从请求队列里取出队首的resolve并执行。next() {if (this.requestQueue.length <= 0) return;const _resolve = this.requestQueue.shift();_resolve();}
}module.exports = RequestDecorator;

样例代码如下:

const RequestDecorator = require('../src/index.js')// 一个callback类型的请求api
function delay(num, time, cb) {setTimeout(() => {cb(null, num);}, time);
}// 通过maxLimit设置并发量限制,needChange2Promise将callback类型的请求api转化为promise类型的。
const requestInstance = new RequestDecorator({maxLimit: 5,requestApi: delay,needChange2Promise: true,
});let promises = [];
for (let i = 0; i < 30; i  ) {// 接下来你就可以像原来使用你的api那样使用它,参数和原来的是一样的promises.push(requestInstance.request(i, Math.random() * 3000).then(result => console.log('result', result), error => console.log(error)));
}
async function test() {await Promise.all(promises);
}test();

这样,一个能对请求并发数做限制的通用RequestDecorator就已经实现了。当然,这里还有很多可以继续增加的功能点,比如

  1. 允许使用者设置每个请求的retry次数。
  2. 允许使用者对每个请求设置缓存处理。

优点:

  1. 不修改用户原来的request api代码。对原有代码无副作用。
  2. 不修改request api的调用方式。用户可以无缝的使用被RequestDecorator封装过的request。
  3. 可扩展,后续可能不止支持并发量限制,还可能增加缓存、retry等额外的功能。

结语

以上,就是本篇的全部内容。github仓库地址点击这里。欢迎大家点赞或者star下。如果大家有兴趣的话,也可以一起来完善这个东西。这个项目还不成熟,可能还会有bug,欢迎大家在github上提issue帮助我完善它。如果觉得有帮助的话,麻烦点个赞哦,谢谢。 本文地址在->本人博客地址, 欢迎给个 start 或 follow

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/367268.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用ActiveMQ和HornetQ通过WebSocket通过STOMP轻松进行消息传递

消息传递是用于构建不同级别的分布式软件系统的极其强大的工具。 通常&#xff0c;至少在Java生态系统中&#xff0c;客户端&#xff08;前端&#xff09;从不直接与消息代理&#xff08;或交换&#xff09;进行交互&#xff0c;而是通过调用服务器端&#xff08;后端&#xff…

yum 安装mysql的位置_Yum安装MySQL以及相关目录路径和修改目录

有些时候,为了方便,有些同学喜欢通过yum的方式安装MySQL,没有设置统一的文件目录以及软件目录,那么就会为后续的维护工作带来很大的麻烦&#xff01;下面就简单介绍一下yum安装MySQL的步骤以及这类安装下的相关目录路径,最后简单介绍下如何更改文件目录&#xff01;YUM安装MySQ…

【laravel】【转发】laravel 导入导出excel文档

1、简介 Laravel Excel 在 Laravel 5 中集成 PHPOffice 套件中的 PHPExcel &#xff0c;从而方便我们以优雅的、富有表现力的代码实现Excel/CSV文件的导入和 导出 。 该项目的GitHub地址是&#xff1a; https://github.com/Maatwebsite/Laravel-Excel 。 本文我们将在Laravel中…

javaScript--DOM

一、JavaScript JavaScript这门语言由 DOM、BOM、ECMAScript 组成。 DOM&#xff1a;document object model 文档对象模型。体现在代码中就是 document 对象。 BOM&#xff1a;browser object model 浏览器对象模型。体现在代码中就是window对象。 ECMA&#xff1a;核心语法。包…

计算机原理及应用课程,课程介绍

《计算机原理及应用》课程的计划学时为70学时&#xff0c;其中课堂授课为58学时&#xff0c;课程实验为12学时。另外&#xff0c;还设置了2周课程综合性实验。三、教学内容(一)理论教学《计算机原理及应用》的课程内容共分为9部分&#xff0c;其具体内容、知识点和课时分配如下…

你真的了解css像素嘛?

在日常开发中&#xff0c;px一定是大家接触过最多的css单位&#xff0c;但是你真的了解px嘛&#xff1f;1px在屏幕中到底是多大呢&#xff1f;另外不知道大家有没有过下面这些疑惑: 为什么一个元素在pc上和移动端的物理尺寸不一样&#xff0c;但是两者的视觉效果上却差不多呢&…

Apache Camel 2.12 –支持后退,以减少较积极的轮询路线

这是另一篇博客文章&#xff0c;介绍了下一个Apache Camel 2.12版本中即将进行的改进和新功能。 在上一个博客中&#xff0c;我谈到了路由直接支持的cron表达式 。 这篇博客文章与之相关&#xff0c;因为我们对轮询路由具有另一个新功能&#xff08;使用计划的轮询使用者&…

django框架概述

------------------MVC与MVT框架------------------- 1、MVCMVC框架的核心思想是&#xff1a;解耦。降低各功能模块之间的耦合性&#xff0c;方便将来变化时&#xff0c;更容易重构代码&#xff0c;最大程度上实现代码的重用。m表示model&#xff0c;重要用于对数据层的封装&am…

小鬼难缠--python小bug备忘

今天编译pyhon做人脸识别&#xff0c;遇到几个问题&#xff0c;做个记录吧。 编译报错&#xff1a; File "harrClassifier.py", line 17, in <module> flagscv2.CV_HAAR_SCALE_IMAGEAttributeError: module object has no attribute CV_HAAR_SCALE_IMAGE 定位根…

mysql for mac中文_mysql for Mac 下创建数据表中文显示为?的解决方法

在我的绝版Mac mini下安装了mysql 5.7版本&#xff0c;实例中&#xff0c;在通过load data 导入数据时发现表中的中文显示为 &#xff1f;通过百度&#xff0c;发现多个版本的解决方法&#xff0c;将其中一个成功解决的方法贴上来&#xff1a;大多方法都是这样&#xff1a;需要…

计算机科学计算方面分为,计算机方面的专业分为哪些类?【资讯与计算科学】和【电脑科学与技术专业】有什么不同?...

计算机方面的专业分为哪些类&#xff1f;【资讯与计算科学】和【电脑科学与技术专业】有什么不同&#xff1f;以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;计算机方面的专业分为哪些类&am…

Java异常处理教程(包含示例和最佳实践)

异常是可能在程序执行期间发生的错误事件&#xff0c;它会破坏其正常流程。 Java提供了一种健壮且面向对象的方式来处理异常情况&#xff0c;称为Java异常处理 。 我们将在本教程中研究以下主题。 Java异常处理概述 异常处理关键字 异常层次 有用的异常方法 Java 7自动资源…

GMTC 大前端时代前端监控的最佳实践

本文来自阿里云前端监控团队&#xff0c;转载请注明出处本文为2018年6月21日&#xff0c;在北京举办的GMTC(全球大前端技术大会)&#xff0c;下午性能与监控专场&#xff0c;由阿里云前端监控团队前端技术专家彭伟春带来的演讲稿&#xff0c;现场反馈效果非常好&#xff0c;地上…

mysql有子查询么_sql-带有子查询的mysql更新查询

谢谢&#xff0c;我不知道使用INNER JOIN进行更新。在原始查询中&#xff0c;错误是要命名子查询&#xff0c;该子查询必须返回一个值&#xff0c;因此不能使用别名。UPDATE CompetitionSET Competition.NumberOfTeams (SELECT count(*) -- no column aliasFROM PicksPointsWHE…

『性能测试』文章大汇总

为了方便阅读&#xff0c;我重新整理本文&#xff0c;将包含本博客所有与性能测试有关的内容。 ------------------------------------------- 近两年市面上的性能测试书籍很多了&#xff0c;但大部分书都在讲loadrunner的操作技巧项目与项目实践。我不认为有什么问题&#xff…

Alpha阶段敏捷冲刺②

1.提供当天站立式会议照片一张 每个人的工作 &#xff08;有work item 的ID&#xff09;&#xff0c;并将其记录在码云项目管理中&#xff1a; 昨天已完成的工作。 购买云服务器 注册账号 界面布局初步规划 今天计划完成的工作。 界面雏形设计 数据库初步设计 完成后端框架初步…

html iframe post,使用Jquery和IFrame的跨子域请求(GET,POST,…)

我正在尝试在我的主域(http://foo.com)和我的API(http://api.foo.com)之间开发请求.为了绕过关于跨子域内容的限制,我在主页(http foo.com/main.html)上使用iframe,指向iframe.html页面&#xff1a;scripts.api.foo.com.(scripts.api.foo.com和foo.com在同一台服务器上,api.foo…

透明地持久保存并从数据库中检索加密的数据

自从我在这里发表上一个帖子以来已经有两个多月了&#xff0c;但是今年六月和七月非常忙碌而密集。 首先&#xff0c; Confitura的组织&#xff08;欧洲最大的Java开发人员免费会议&#xff09;参加了我所有的免费晚会&#xff0c;然后在相当紧张的住院期间&#xff0c;我们的第…

[译] 2017 年比较 Angular、React、Vue 三剑客

原文地址&#xff1a;Angular vs. React vs. Vue: A 2017 comparison原文作者&#xff1a;Jens Neuhaus译文出自&#xff1a;掘金翻译计划本文永久链接&#xff1a;https://github.com/xitu/gold-miner/blob/master/TODO/angular-vs-react-vs-vue-a-2017-comparison.md译者&…

centos 离线安装mysql_CentOS6离线安装mysql-5.7.25

1.mysql-5.7.25-1.el6.x86_64.rpm-bundle.tar下载百度云资源提取码&#xff1a;ej1y2.把下载的mysql安装包上传到Centos上解压mysql&#xff0c;我这是在Windows上解压的上传到Centos上&#xff0c;我在Centos上解压mysql不知道为什么少了rpm -ivh mysql-community-common-5.7.…