连续执行Promise.all

时间:2016-05-12 20:20:44

标签: javascript node.js promise

我有一个包含promises数组的数组,每个内部数组可以有4k,2k或500个promise。

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

现在我需要执行.Block( System.Int32 $propertyValue, System.Object[] $array, System.Int32 $length, System.Int32 $index, System.Boolean $result) { $propertyValue = $x.Bar; $array = .Call .Constant<System.Collections.Generic.List`1[System.Object]>(System.Collections.Generic.List`1[System.Object]).ToArray(); $length = $array.Length; $index = 0; $result = False; .Loop { .If ($index < $length) { .Block() { .If ($propertyValue == (System.Int32)$array[$index]) { .Block() { $result = True; .Break endLoop { } } } .Else { .Default(System.Void) }; $index++ } } .Else { .Break endLoop { } } } .LabelTarget endLoop:; $result }

完成第一个内部数组后,我需要执行下一个Promise.all(BigArray[0]),依此类推等等。

如果我尝试执行Promise.all(BigArray[1])投掷:

  

致命错误call_and_retry_2分配失败 - 处理内存不足

我需要将每个promises串行执行,而不是并行执行,我认为这就是Node所做的。 我不应该使用新的库,但我愿意考虑答案!。

编辑:

以下是一段代码示例:

Promise.all(BigArray)

5 个答案:

答案 0 :(得分:1)

Promise.all()将检查作为 parallel 中的参数传递的每个promise结果,并在第一个错误时拒绝,或在完成所有promise后解析。

来自MDN

  

Promise.all传递来自传递的可迭代对象中所有promise的值数组。值数组维护原始可迭代对象的顺序,而不是promises被解析的顺序。如果在可迭代数组中传递的东西不是promise,则由Promise.resolve转换为1。如果任何传入的承诺拒绝,所有承诺立即拒绝拒绝的承诺的价值,放弃所有其他承诺,无论他们是否已经解决。如果传递了一个空数组,则此方法立即解析。

如果您需要系列执行所有承诺,那么Promise.all()方法将 用于您的应用。相反,您需要找到一种解决您的承诺的迭代方法。这将很困难; node.js本质上是异步的,并且使用循环(根据我的知识和经验),在循环中从promise中收到响应之前不会阻塞。

修改

存在一个名为promise-series-node的库,我认为这可能会对你有所帮助。由于您已经创建了承诺,因此您可以将其传递给BigArray

promiseSeries(BigArray).then( (results) => {
   console.log(results);
});

在我个人看来,你从60k +承诺开始的方法不仅需要花费大量的时间,而且还需要系统执行它们的资源(这就是你内存不足的原因)。我认为您可能需要考虑更好的应用程序架构。

Edit2,承诺是什么?:

promise表示异步操作的结果,它可以采用以下三种状态之一:

  1. 待定:承诺的开始状态
  2. 实现:成功运作所代表的承诺状态
  3. 拒绝:操作失败所代表的承诺状态
  4. 一旦承诺履行或被拒绝,承诺就是不可改变的。你可以链接promises(非常适合避免重复的回调),以及嵌套它们(当关闭是一个问题时)。网上有很多很棒的文章,here is one I found to be informative

答案 1 :(得分:1)

在ES2017中使用async / await非常简单:

(async () => {
    for (let i = 0; i < BigArray.length; i++) {
        await Promise.all(BigArray(i));
    }
})();

答案 2 :(得分:0)

promise库bluebird提供了一个名为Promise.map的辅助方法,它将数组或数组的promise作为其第一个参数,并将其所有元素映射到结果数组,而结果数组又得到了保证。也许你可以尝试这样的事情:

UPDATE [Items] 
SET [IsInSeason] = 1 
WHERE [Name] like '%summer%'

但如前所述,这仍然是一项非常耗费资源的任务,可能会占用所有可用内存。

答案 3 :(得分:0)

这里的答案很好Callback after all asynchronous forEach callbacks are completed

function asyncFunction (item, cb) {
  setTimeout(() => {
    console.log('done with', item);
    cb(item*10);
  }, 1000*item);
}



let requests = [1,2,3].map((item) => {
    return new Promise((resolve) => {
      asyncFunction(item, resolve);
    });
})

Promise.all(requests).then(
//  () => console.log('done')
    function(arr){
        console.log(arr)
         console.log('done')
    }
    );

答案 4 :(得分:0)

Promise.all无法使用,您可以使用Array.reduce逐个处理BigArray元素:

BigArray.reduce((promiseChain, currentArray) => {
    return promiseChain.then(chainResults =>
        Promise.all(currentArray).then(currentResult =>
            [...chainResults, currentResult]
        )
    );
}, Promise.resolve([])).then(arrayOfArraysOfResults => {
    // Do something with all results
});