执行一系列的承诺。 一旦Promise.all完成,进入下一批

我有一个数组,其中包含承诺数组,每个内部数组可以有4k,2k或500个承诺。

总共有大约60K的承诺,我也可以用其他值来testing它。

现在我需要执行Promise.all(BigArray [0])。

一旦第一个内部数组完成,我需要执行下一个Promise.all(BigArray [1])等等。

如果我尝试执行一个Promise.all(BigArray)它的投掷:

致命的错误call_and_retry_2分配失败 – 进程内存不足我需要执行它的每个承诺串联,而不是并行,我认为这是什么节点它的事情。 我不应该使用新的库,但是我愿意考虑答案!

编辑:

以下是一段代码示例:

function getInfoForEveryInnerArgument(InnerArray) { const CPTPromises = _.map(InnerArray, (argument) => getDBInfo(argument)); return Promise.all(CPTPromises) .then((results) => { return doSomethingWithResults(results); }); } function mainFunction() { BigArray = [[argument1, argument2, argument3, argument4], [argument5, argument6, argument7, argument8], ....]; //the summ of all arguments is over 60k... const promiseArrayCombination = _.map(BigArray, (InnerArray, key) => getInfoForEveryInnerArgument(InnerArray)); Promise.all(promiseArrayCombination).then((fullResults) => { console.log(fullResults); return fullResults; }) } 

你的问题有一点误会,这个问题可能会让这个问题中的一些人和这个问题的前一个版本混淆。 您正尝试执行一系列asynchronous操作,一批操作,然后执行另一批操作。 这些asynchronous操作的结果被承诺跟踪。 承诺本身代表已经开始的asynchronous操作。 “承诺”不是自己执行的。 所以在技术上,你不要“执行一系列的承诺”。 您执行一组操作,用承诺跟踪其结果,然后在第一批完成时执行下一批。

无论如何,这是一个序列化每批操作的解决scheme。

你可以创build一个内部函数,我通常会调用next()来让你处理每个迭代。 当promise从处理一个innerArrayparsing时,你再次调用next()

 function mainFunction() { return new Promise(function(resolve, reject) { var bigArray = [[argument1, argument2, argument3, argument4], [argument5, argument6, argument7, argument8], ....]; //the summ of all arguments is over 60k... var results = []; var index = 0; function next() { if (index < bigArray.length) { getInfoForEveryInnerArgument(bigArray[index++]).then(function(data) { results.push(data); next(); }, reject); } else { resolve(results); } } // start first iteration next(); }); } 

这也将所有子结果收集到一个结果数组中,并返回一个parsing值为这个结果数组的主承诺。 所以,你可以使用这个:

 mainFunction().then(function(results) { // final results array here and everything done }, function(err) { // some error here }); 

您也可以使用.reduce()devise模式来串行迭代数组:

 function mainFunction() { var bigArray = [[argument1, argument2, argument3, argument4], [argument5, argument6, argument7, argument8], ....]; return bigArray.reduce(function(p, item) { return p.then(function(results) { return getInfoForEveryInnerArgument(item).then(function(data) { results.push(data); return results; }) }); }, Promise.resolve([])); } 

这比第一个选项创造了更多的同时承诺,我不知道这是否是一个大的承诺(这就是为什么我提供了原始选项)的问题,但是这个代码更清洁,概念使用方便对于其他情况。


仅供参考,有一些承诺附加function为您做这个。 在蓝鸟承诺库 (这是一个使用承诺开发的伟大库),他们有Promise.map()这是为此:

 function mainFunction() { var bigArray = [[argument1, argument2, argument3, argument4], [argument5, argument6, argument7, argument8], ....]; return Promise.map(bigArray, getInfoForEveryInnerArgument); } 

你可以recursion地做,例如在这里我需要在Mongo里面放大约60k的文件,但是它太大了,一步到位,所以我拿1k文件,把它们发送给mongo,另外1K文件等

 exports.rawRecursive = (arr, start) => { //ending condition if (start > arr.length) { return; } Rawmedicament.insertManyAsync(_.slice(arr, start, start + 1000)).then(() => { //recursive exports.rawRecursive(arr, start + 1000); }); }; 

如果你想注意,当一切都完成,你可以在结束条件放callback,或者如果你喜欢承诺你可以在那里调用resolve()。

另外,如果原始数组不是承诺,而是应该处理的对象,则可以使用Array.prototype.map()Array.prototype.slice()Promise.all() Array.prototype.map()来组合无需外部依赖的Promise.all()

 // Main batch parallelization function. function batch(tasks, pstart, atonce, runner, pos) { if (!pos) pos = 0; if (pos >= tasks.length) return pstart; var p = pstart.then(function() { output('Batch:', pos / atonce + 1); return Promise.all(tasks.slice(pos, pos + atonce).map(function(task) { return runner(task); })); }); return batch(tasks, p, atonce, runner, pos + atonce); } // Output function for the example function output() { document.getElementById("result").innerHTML += Array.prototype.slice.call(arguments).join(' ') + "<br />"; window.scrollTo(0, document.body.scrollHeight); } /* * Example code. * Note: Task runner should return Promise. */ function taskrunner(task) { return new Promise(function(resolve, reject) { setTimeout(function() { output('Processed:', task.text, 'Delay:', task.delay); resolve(); }, task.delay); }); } var taskarray = []; function populatetasks(size) { taskarray = []; for (var i = 0; i < size; i++) { taskarray.push({ delay: 500 + Math.ceil(Math.random() * 50) * 10, text: 'Item ' + (i + 1) }); } } function clean() { document.getElementById("result").innerHTML = ''; } var init = Promise.resolve(); function start() { var bsize = parseInt(document.getElementById("batchsize").value, 10), tsize = parseInt(document.getElementById("taskssize").value, 10); populatetasks(tsize); init = batch(taskarray.slice() /*tasks array*/ , init /*starting promise*/ , bsize /*batch size*/ , taskrunner /*task runner*/ ); } 
 <input type="button" onclick="start()" value="Start" /> <input type="button" onclick="clean()" value="Clear" />&nbsp;Batch size:&nbsp; <input id="batchsize" value="4" size="2"/>&nbsp;Tasks:&nbsp; <input id="taskssize" value="10" size="2"/> <pre id="result" />