javascript编程中的promise(JavaScript如何利用Promise控制并发请求个数)
javascript编程中的promise
JavaScript如何利用Promise控制并发请求个数一、场景
假设现在有这么一种场景:现有 30 个异步请求需要发送,但由于某些原因,我们必须将同一时刻并发请求数量控制在 5 个以内,同时还要尽可能快速的拿到响应结果。
如图所示:
上图这样的排队和并发请求的场景基本类似,窗口只有三个,人超过三个之后,后面的人只能排队了。
二、串行和并行
- 串行:一个异步请求完了之后在进行下一个请求
- 并行:多个异步请求同时进行
串行举例:
var p = function () { return new Promise(function (resolve, reject) { setTimeout(() => { console.log("1000"); resolve(); }, 1000); }); }; var p1 = function () { return new Promise(function (resolve, reject) { setTimeout(() => { console.log("2000"); resolve(); }, 2000); }); }; var p2 = function () { return new Promise(function (resolve, reject) { setTimeout(() => { console.log("3000"); resolve(); }, 3000); }); }; p() .then(() => { return p1(); }) .then(() => { return p2(); }) .then(() => { console.log("end"); });
如示例,串行会从上到下依次执行对应接口请求。
并行举例:
通常,我们在需要保证代码在多个异步处理之后执行,会用到:
Promise.all((promises: [])).then((fun: function));
Promise.all可以保证,promises数组中所有promise对象都达到resolve状态,才执行then回调。
var promises = function () { return [1000, 2000, 3000].map((current) => { return new Promise(function (resolve, reject) { setTimeout(() => { console.log(current); }, current); }); }); }; Promise.all(promises()).then(() => { console.log("end"); });
这时候考虑一个场景:
如果你的promises数组中每个对象都是http请求,而这样的对象有几十万个。
那么会出现的情况是,你在瞬间发出几十万个http请求,这样很有可能导致堆积了无数调用栈导致内存溢出。
这时候,我们就需要考虑对Promise.all做并发限制。
Promise.all并发限制指的是,每个时刻并发执行的promise数量是固定的,最终的执行结果还是保持与原来的Promise.all一致。
三、代码实现
整体采用递归调用来实现:最初发送的请求数量上限为允许的最大值,并且这些请求中的每一个都应该在完成时继续递归发送,通过传入的索引来确定了urls里面具体是那个URL,保证最后输出的顺序不会乱,而是依次输出。
代码:
function multiRequest(urls, maxNum) { const len = urls.length; // 请求总数量 const res = new Array(len).fill(0); // 请求结果数组 let sendCount = 0; // 已发送的请求数量 let finishCount = 0; // 已完成的请求数量 return new Promise((resolve, reject) => { // 首先发送 maxNum 个请求,注意:请求数可能小于 maxNum,所以也要满足条件2 // 同步的 创建maxNum个next并行请求 然后才去执行异步的fetch 所以一上来就有5个next并行执行 while (sendCount < maxNum && sendCount < len) { next(); } function next () { let current = sendCount ++; // 当前发送的请求数量,后加一 保存当前请求url的位置 // 递归出口 if (finishCount >= len) { // 如果所有请求完成,则解决掉 Promise,终止递归 resolve(res); return; } const url = urls[current]; fetch(url).then(result => { finishCount ++; res[current] = result; if (current < len) { // 如果请求没有发送完,继续发送请求 next(); } }, err => { finishCount ++; res[current] = err; if (current < len) { // 如果请求没有发送完,继续发送请求 next(); } }); } }); }
总结:
代码在while循环处创建了maxNum个"请求窗口"来进行请求,从而达到并行效果,然后next函数中进行异步请求,然后通过在.then里面进行递归进行新请求的调用,实现"一个窗口只进行一个请求,当这个请求执行完成后才进行下一个请求"(每个窗口串行执行,maxNum个窗口并行执行)。
到此这篇关于JavaScript如何利用Promise控制并发请求个数的文章就介绍到这了,更多相关js用Promise控制并发请求内容请搜索开心学习网以前的文章或继续浏览下面的相关文章希望大家以后多多支持开心学习网!
参考链接
1、https://www.jb51.net/article/211898.htm
2、https://www.jb51.net/article/212277.htm
- javascript编程中的promise(JavaScript如何利用Promise控制并发请求个数)
- jspromise原理(JavaScript使用promise处理多重复请求)
- 前端面试题之promise的手动封装(Promise面试题详解之控制并发)
- 太鸡贼了,这老小区轻松搞定了停车问题(这老小区轻松搞定了停车问题)
- 太鸡贼了,这老小区轻松搞定了停车问题(这老小区轻松搞定了停车问题)
- 节日我在岗|警景相融 平安相伴(节日我在岗警景相融)
- 战 疫 时刻 致敬每一位石化大学的 守护者(战疫时刻)
- 老弄堂里的市井味道(老弄堂里的市井味道)
- 小米音乐可绑定QQ音乐, QQ音乐 真的会消失在小米的设备上吗(小米音乐可绑定QQ音乐)
热门推荐
- sqlserver非唯一索引汇总性能(详解SQL Server的聚焦过滤索引)
- Docker 部署单机版 Pulsar 和集群架构 Redis(开发神器)的方法(Docker 部署单机版 Pulsar 和集群架构 Redis开发神器的方法)
- mysql索引b+树和b树(MySQL使用B+Tree当索引的优势有哪些)
- rename重命名mysql表(MySQL 重命名表的操作方法及注意事项)
- 怎么查看云服务器的配置(云服务器配置参数如何选择)
- laravel模型详解(laravel config文件配置全局变量的例子)
- laravel入门教程零基础(Laravel5.7框架安装与使用学习笔记图文详解)
- python爬虫并保存excel实例(Python实现爬取亚马逊数据并打印出Excel文件操作示例)
- dedecms内容页代码(DEDECMS生成HTML时提示 DedeTag Engine Create File False的解决方法)
- 阿里云服务器可以连接几个面板(阿里云云服务器宝塔面板的安装图文教程详解)