当前位置: 首页 > 科技观察

几百条数据,Promise.all没有控制并发?那你的心真大!

时间:2023-03-13 06:44:53 科技观察

需求最近在做一个需求:把一些东西批量存入数据库,一次可能达到几百个,也就是说我一次需要存入数据库几百次。我是这样做的:constsave=(data)=>{//数据库操作(Promise)returninsert(data)}constdatas=[...hundredsofdata]//storePromise.all(datas.map(救))被骂就是在我觉得需要的时候很容易。.在CodeReview上,我被团队的老大骂了一顿。原因是:存储操作发生在服务器上,服务器非常脆弱。如果一次存储上百个文件,服务器挂了怎么办?然后大佬们提出了一个解决方案:控制并发,大佬们真的很强,感觉这种事情已经是大佬们的常规操作了。.控制Promise.all的并发度就是说,比如我有几百个存储操作,我不能一次全部执行完,而是一次只控制10个操作,如果10个操作有一个完成,我会接受的。添加执行的操作,依此类推,直到执行完所有这数百个操作。.其实很简单,直接用库就可以了,比如async-pool,es6-promise-pool,p-limit,只要能用库,建议不要自己写,因为有不确定的因素很多,没有库必须自己写写的好,你觉得呢~简单的实现看到有师兄实现的很好,链接:https://segmentfault.com/a/1190000016389127这个才是核心异步池库的源代码:functionasyncPool(poolLimit,array,iteratorFn){leti=0;constret=[];const执行=[];constenqueue=function(){//边界处理,数组为空数组if(i===array.length){returnPromise.resolve();}//每次调用入队时,都会初始化一个promiseconstitem=array[i++];constp=Promise.resolve().then(()=>iteratorFn(item,array));//放入promises数组ret.push(p);//promise被执行,从执行数组中删除conste=p.then(()=>executing.splice(executing.indexOf(e),1));//插入执行编号以指示正在执行的承诺executing.push(e);//使用Promise.rece,每当执行数组中的promise数量低于poolLimit时,实例化一个新的promise并执行letr=Promise.resolve();if(executing.length>=poolLimit){r=Promise.race(执行);}//递归直到遍历数组returnr.then(()=>enqueue());};returnenqueue().then(()=>Promise.all(ret));}大致逻辑可以概括为:从数组第一个元素开始,初始化promise对象,同时使用一个executing数组保存正在执行的promise继续初始化promise,直到达到poolLimt使用Promise.race获取promiseinexecution执行状态,当一个promise被执行时,继续初始化promise并投入执行。所有的promise执行完毕后,调用Promise.all返回。用法:consttimeout=i=>newPromise(resolve=>setTimeout(()=>resolve(i),i));返回异步池(2,[1000、5000、3000、2000],超时)。然后(结果=>{...});