Javascript 给定一个异步函数列表,如何一次处理n个?

Javascript 给定一个异步函数列表,如何一次处理n个?,javascript,promise,async-await,Javascript,Promise,Async Await,JavaScript提供了一种收集承诺列表的机制: const tasks = [ fetch('a'), fetch('b'), fetch('c') ]; const results = await Promise.all(tasks); 但是,如果我想执行所有任务,但只同时执行n,该怎么办 const results = await MorePromise.allWithConcurrency(2, tasks); // 2 at a time JavaScript提供了这样的功能

JavaScript提供了一种收集承诺列表的机制:

const tasks = [ fetch('a'), fetch('b'), fetch('c') ];

const results = await Promise.all(tasks); 
但是,如果我想执行所有任务,但只同时执行
n
,该怎么办

const results = await MorePromise.allWithConcurrency(2, tasks); // 2 at a time

JavaScript提供了这样的功能吗?如果没有,是否有可靠的库可以这样做

您可以使用类似于
bluebird
的插件来实现它,该插件有一个允许它:


你也可以自己创建一个函数来处理它。这是我自己编的一个函数,ofc,它是可以改进的

constresultpromises=[];
设nextToCall=0;
让错误发生=错误;
/**
*执行一个承诺时调用的函数
*/
函数callbackOnePromiseGotExecuted({
错误,
结果,,
allExecutedCallback,
阵列,
}) {
resultPromises.push(结果);
//如果报告错误,则不执行任何操作
如果(发生错误){
返回;
}
//返回错误
如果(错误){
allExecutedCallback(null,resultPromises);
ErrorOccessed=true;
返回;
}
//检查这是否是执行的最后一个承诺
if(resultPromises.length==array.length){
allExecutedCallback(null,resultPromises);
返回;
}
nextToCall+=1;
//如果我们已经完成了一切,就停下来
if(nextToCall>array.length)返回;
//如果不是新的承诺
数组[nextToCall-1]。调用()
。然后(ret=>callbackOnePromiseGotExecuted({
错误:null,
结果:ret,
allExecutedCallback,
阵列,
}))
.catch(e=>callbackOnePromiseGotExecuted({
错误:e,
结果:空,
allExecutedCallback,
阵列,
}));
}
/**
*并发处理多承诺的调用
*/
功能承诺与并发回调({
阵列,
并发号码,
allExecutedCallback,
}) {
for(设i=0;icallbackOnePromiseGotExecuted({
错误:null,
结果:ret,
allExecutedCallback,
阵列,
}))
.catch(e=>callbackOnePromiseGotExecuted({
错误:e,
结果:空,
allExecutedCallback,
阵列,
}));
nextToCall+=1;
}
}
函数promiseWithConcurrency(数组、concurrencyNumber){
返回新承诺((解决、拒绝)=>{
同意收回承诺书({
阵列,
并发号码,
allExecutedCallback:(错误,结果)=>{
如果(错误)返回拒绝(错误);
返回解析(结果);
},
});
});
}
常量数组=[
()=>新承诺((决议)=>决议('01'),
()=>新承诺((决议)=>决议('02'),
()=>新承诺((决议)=>决议('03'),
()=>新承诺((决议)=>决议('04'),
()=>新承诺((决议)=>决议('05'),
()=>新承诺((决议)=>决议('06'),
];
promiseWithConcurrency(数组,2)
.then(rets=>console.log('rets',rets))

.catch(error=>console.log('error',error))使用纯JS ES6如何

var ps=[Promise.resolve(1)、Promise.resolve(2)、Promise.resolve(3)、Promise.resolve(4)、Promise.resolve(5)],
groupBy=(n,a)=>a.reduce((r,p,i)=>!(i%n)?(r.push([p]),r):(r[r.length-1]。push(p,r),[]);
groupBy(2,ps).map(sps=>Promise.all(sps).then(console.log))
。作为控制台包装器{
最大高度:100%!重要;

}
“JavaScript提供了这样的功能吗?”->否。“如果没有,是否有任何强大的库可以提供?”->不在SO和SO范围内,因此offtopic+
fetch('a')
不是异步函数,它在您的解决方案中产生了一个承诺,所有函数都被调用,然后两个接一个地解析。但重要的是他们都是同时被处决的。例如,使用这个:
varps=[newpromise((resolve)=>{console.log('A');setTimeout(()=>resolve(1),5000);}),Promise.resolve(2),Promise.resolve(3),Promise.resolve(4),Promise.resolve(5)]。因此,如果OP想要两个接两个地做事情,它将不起作用。您只需两个两个地解析。@Grégory NEUT No。它将完美地两个两个地运行承诺,您可以在
中应用您的逻辑。然后(console.log)
部分,例如
。然后(doSomething)
每对<代码>doSomething
将在最新一对完成时调用。@Grégory NEUT我找到你了。我最初的想法是处理手头已有的承诺,然后分组处理它们的
。您知道fetchapi有很多链接的
then()
阶段。然而你是对的。我添加了两种备选解决方案。
const Promise = require('bluebird');
const _ = require('lodash');

let tasks = [...]; // over 10,000 items.

Promise.all(
  _(tasks).map(task => {
    return task.doAsyncThing();
  })
    .value();
);

Promise.map(
  tasks, 
  task => {
    return task.doAsyncThing();
  }, 
  { concurrency: 1000 }
);