对请求并发数做限制的通用RequestDecorator
使用场景
在开发中,我们可能会遇到一些对异步请求数做并发量限制的场景,比如说微信小程序的request并发最多为5个,又或者我们需要做一些批量处理的工作,可是我们又不想同时对服务器发出太多请求(可能会对服务器造成比较大的压力)。这个时候我们就可以对请求并发数进行限制,并且使用排队机制让请求有序的发送出去。
介绍
那么,接下来我们就来讲一下如何实现一个通用的能对请求并发数进行限制的RequestDecorator。我们先来介绍一下它的功能:
- 既然涉及到并发数限制,它就肯定允许用户传入最大并发数限制参数:maxLimit
- 既然是一个通用的RequestDecorator,那么它应该允许使用者传入其喜欢的异步api(比如ajax, fetch, axios等)。
- 为了方便起见,也为了开发便利性,被RequestDecorator封装后的request请求结果都返回一个promise。
- 由于使用者传入的异步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;
}
// 发起请求api
async 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
async 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就已经实现了。当然,这里还有很多可以继续增加的功能点,比如
- 允许使用者设置每个请求的retry次数。
- 允许使用者对每个请求设置缓存处理。
结语
以上,就是本篇的全部内容。github仓库地址点击这里。欢迎大家点赞或者star下。如果大家有兴趣的话,也可以一起来完善这个东西。这个项目还不成熟,可能还会有bug,欢迎大家在github上提issue帮助我完善它。如果觉得有帮助的话,麻烦点个赞哦,谢谢。
转:https://www.cnblogs.com/chenjg/p/9638613.html
对请求并发数做限制的通用RequestDecorator的更多相关文章
- 不到50行代码实现一个能对请求并发数做限制的通用RequestDecorator
使用场景 在开发中,我们可能会遇到一些对异步请求数做并发量限制的场景,比如说微信小程序的request并发最多为5个,又或者我们需要做一些批量处理的工作,可是我们又不想同时对服务器发出太多请求(可能会 ...
- Node爬虫之——使用async.mapLimit控制请求并发
一般我们在写爬虫的时候,很多网站会因为你并发请求数太多当做是在恶意请求,封掉你的IP,为了防止这种情况的发生,我们一般会在代码里控制并发请求数,Node里面一般借助async模块来实现. 1. asy ...
- 吞吐量(Throughput)、QPS、并发数、响应时间(RT)对系统性能的影响
首先对吞吐量().QPS.并发数.响应时间(RT)几个概念一直比较模糊,也不知道哪些指标可以较好的衡量系统的性能.今天特意查了些资料做一些记录:首先看一些概念(来自百度百科) 1. 响应时间(RT) ...
- 吞吐量(TPS)、QPS、并发数、响应时间(RT)概念
开发的原因,需要对吞吐量(TPS).QPS.并发数.响应时间(RT)几个概念做下了解,查自百度百科,记录如下:1. 响应时间(RT) 响应时间是指系统对请求作出响应的时间.直观上看,这个指标与人对软 ...
- [笔记]吞吐量(TPS)、QPS、并发数、响应时间(RT)概念
开发的原因,需要对吞吐量(TPS).QPS.并发数.响应时间(RT)几个概念做下了解,查自百度百科,记录如下: 1. 响应时间(RT) 响应时间是指系统对请求作出响应的时间.直观上看,这个指标与人对软 ...
- paip.提升性能---- 网站并发数的总结.txt
paip.提升性能---- 网站并发数的总结.txt 作者Attilax , EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn.n ...
- 【转载】nginx 并发数问题思考:worker_connections,worker_processes与 max clients
注:这个文章主要是作者一直在研究nginx作为http server和反向代理服务器时候所谓最大的max_clients和 worker_connections的计算公式, 其实最后的结论也没有卡上公 ...
- windows下修改apache并发数
还没有尝试 修改apache的最大连接数,方法如下: 步骤一 先修改 /path/apache/conf/httpd.conf文件. # vi httpd.conf 将“#Include conf/e ...
- tomcat 最大并发数
只针对BIO模式,目标请求会sleep两秒再返回结果,通过jmeter测试工具进行并发测试 操作系统:windows && linux tomcat7测试: <Connector ...
随机推荐
- Android TimeAnimator
TimeAnimator:提供了一个简单的回调机制,通过 TimeAnimator.TimeListener,在动画的每一帧处通知你.这个动画器没有时间,插值或是对象值设定.回调监听器为每一帧动画接受 ...
- 【splunk】用正则表达式提取字段
设input输入数据为 http://192.168.23.121/xxx 想提取出里面的ip,可以用rex source="xxx.csv" |rex field=input ...
- 使用caffe模型测试图片(python接口)
1.加载相关模块 1.1 加载numpy import numpy as np 1.2 加载caffe 有两种方法. 方法一(静态导入): 找到当前环境使用的python的site-packages目 ...
- hdu5358 推公式+在一个区间内的尺取+枚举法
尺取+枚举,推出公式以后就是一个枚举加尺取 但是这题的尺取不是对一个值尺取,而是在一个区间内,所以固定左边界,尺取右边界即可 #include<bits/stdc++.h> #define ...
- bzoj 2142
数论大集合 只要你做完了这道题,除了线性筛和降幂公式以外,所有数论noip知识点就都会了... 题意:求C(n,∑w)*C(∑w,w1)*C(∑w-w1,w2).....mod p(不保证p为质数) ...
- Angular2学习(一)
Angular2的新特性: angular2的核心: 模块.组件.元数据.模板.数据绑定.服务.指令.依赖注入.模块. 组件:层层嵌套,形成组件树.父子组件沟通有输入和输出接口 组件包含JavaScr ...
- 【C++ Primer 第13章】6.对象移动
右值引用 左值和右值 (1)两者区别: ①左值:能对表达式取地址.或具名对象/变量.一般指表达式结束后依然存在的持久对象. ②右值:不能对表达式取地址,或匿名对象.一般指表达式结束就不再存在的临时对象 ...
- hdu 1372 骑士从起点走到终点的步数 (BFS)
给出起点和终点 求骑士从起点走到终点所需要的步数 Sample Inpute2 e4 //起点 终点a1 b2b2 c3a1 h8a1 h7h8 a1b1 c3f6 f6 Sample OutputT ...
- poj 1321 棋盘问题(n行中放任意k行)
n*n的棋盘摆K的棋子,任意两个棋子不能在同一行同一列 Sample Input 2 1#. //# 可放.#4 4...#..#..#..#...-1 -1Sample Output 21 # i ...
- [转] equals和==的区别小结
==: == 比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象.比较的是真正意义上的指针操作. 1.比较的是操作符两端的操作数是否是同一个对象 ...