use*_*966 12 javascript batching node.js promise
我有一个包含promises数组的数组,每个内部数组可以有4k,2k或500个promise.
总共有大约60k的承诺,我也可以用其他值来测试它.
现在我需要执行Promise.all(BigArray[0])
.
一旦第一个内部数组完成,我需要执行下一个Promise.all(BigArray[1])
,依此类推,依此类推.
如果我尝试执行Promise.all(BigArray)
它的抛出:
fatal error call_and_retry_2 allocation failed - process out of memory
Run Code Online (Sandbox Code Playgroud)
我需要按顺序执行每个promises,而不是并行执行它,我认为这就是Node正在做的事情.我不应该使用新的库,但我愿意考虑答案!
编辑:
这是一段代码示例:
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;
})
}
Run Code Online (Sandbox Code Playgroud)
jfr*_*d00 10
你的问题有点错误,可能会让这个问题的一些人和这个问题的前一版本感到困惑.您正在尝试串行执行一批异步操作,一批操作,然后在完成后执行另一批操作.使用promises跟踪这些异步操作的结果.Promise本身代表已经启动的异步操作."承诺"不是自己执行的.所以从技术上讲,你不会"连续执行一批承诺".您执行一组操作,使用promises跟踪其结果,然后在第一批完成后执行下一批操作.
无论如何,这是一个序列化每批操作的解决方案.
您可以创建一个我通常调用的内部函数next()
,让您处理每次迭代.当承诺通过处理一个innerArray结算时,您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();
});
}
Run Code Online (Sandbox Code Playgroud)
这也会将所有子结果收集到结果数组中,并返回一个主承诺,其解析值是此结果数组.所以,你可以这样使用:
mainFunction().then(function(results) {
// final results array here and everything done
}, function(err) {
// some error here
});
Run Code Online (Sandbox Code Playgroud)
您还可以使用.reduce()
设计模式连续迭代数组:
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([]));
}
Run Code Online (Sandbox Code Playgroud)
这比第一个选项创建了更多的同时承诺,我不知道这对于如此大量的承诺是否是一个问题(这就是我提供原始选项的原因),但这个代码更清晰,概念使用方便对于其他情况.
仅供参考,我们为您提供了一些承诺附加功能.在Bluebird promise库(使用promises进行开发的一个很棒的库)中,它们具有Promise.map()
以下功能:
function mainFunction() {
var bigArray = [[argument1, argument2, argument3, argument4], [argument5, argument6, argument7, argument8], ....];
return Promise.map(bigArray, getInfoForEveryInnerArgument);
}
Run Code Online (Sandbox Code Playgroud)
2020 年 10 月的回答。 Async/await 使其简短:只有 10 行代码 + JSDoc。
/**
* Same as Promise.all(items.map(item => task(item))), but it waits for
* the first {batchSize} promises to finish before starting the next batch.
*
* @template A
* @template B
* @param {function(A): B} task The task to run for each item.
* @param {A[]} items Arguments to pass to the task for each call.
* @param {int} batchSize
* @returns {B[]}
*/
async promiseAllInBatches(task, items, batchSize) {
let position = 0;
let results = [];
while (position < items.length) {
const itemsForBatch = items.slice(position, position + batchSize);
results = [...results, ...await Promise.all(itemsForBatch.map(item => task(item)))];
position += batchSize;
}
return results;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
7971 次 |
最近记录: |