当前位置: 首页 > Web前端 > JavaScript

Promise并发控制

时间:2023-03-27 00:25:41 JavaScript

题目需要写一个方法来控制promise并发数,如下:promiseConcurrencyLimit(limit,array,iteratorFn)limit是同时执行的promise数,array是参数数组,和iteratorFn是在每个promise中执行的异步操作。在后台开发中,需要在处理多个promise后执行后置逻辑。通常使用Promise.all:Promise.all([p1,p2,p3]).then((res)=>...)但是有个问题是的,因为promise创建后会立即执行,也就是说,传入promise.all的多个promise实例在创建的时候就已经开始执行了。如果这些实例中执行的异步操作都是http请求,那么瞬间就会发送n个http请求,这显然是不合理的;比较合理的做法是在Promise.all中限制异步操作??的个数,只允许limit异步操作同时执行。思路&实现后台提到promise创建后会立即执行,所以控制并发的核??心是控制promise实例的生成。一开始只生成limitpromise实例,然后等待这些promise状态变化。只要其中一个promise实例的状态发生变化,就会立即创建另一个promise实例……以此类推,直到创建并执行所有promise。npm上有很多库实现了这个功能。个人觉得tiny-async-pool这个库更好一些,因为它直接使用原生的Promise来实现这个功能,而其他的库大多是重新实现promise。其核心代码如下:asyncfunctionasyncPool(poolLimit,array,iteratorFn){constret=[];//用于存储所有的promise实例constexecuting=[];//用于存储当前执行的承诺for(constitemofarray){constp=Promise.resolve(iteratorFn(item));//防止回调函数返回一个promise,用Promise.resolve包裹ret.push(p);if(poolLimit<=array.length){//在then回调中,当promise状态变为fulfilled时,将其从正在执行的promise列表中删除executingconste=p.then(()=>executing.splice(executing.indexOf(e),1));执行.push(e);if(executing.length>=poolLimit){//一旦正在执行的promise列表的数量等于限制数量,使用Promise.race等待一个promise状态改变,//状态改变之后,上面的thencallback会被执行,promise会被删除执行,//然后进入下一个for循环生成一个新的promise来补充awaitPromise.race(executing);}}}returnPromise.all(ret);}测试代码如下:consttimeout=(i)=>{console.log('start',i);returnnewPromise((resolve)=>setTimeout(()=>{resolve(i);console.log('end',i);},i));};(async()=>g吨;{constres=awaitasyncPool(2,[1000,5000,3000,2000],超时);控制台日志(资源);})();代码的核心思想是:首先初始化limitpromise实例,将其放入executing数组中,使用Promise.race等待limitpromise实例的执行结果。一旦某个promise的状态发生变化,将其从execution中删除,然后执行循环生成一个新的promise,放入execution中重复步骤2和3,直到所有promise执行完毕,最后使用Promise.all返回执行所有承诺实例的结果