2016-05-12 55 views
3

我有一个包含promise数组的数组,每个inner数组可以有4k,2k或500个promise。执行Promise.all系列

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

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

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

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

致命错误call_and_retry_2分配失败 - 加工出来的内存

我需要并行执行它的每个承诺串联,不我认为这就是它在做什么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; 
    }) 
} 
+4

答案试图跟踪的60K承诺的状态听起来像是一场噩梦,我不是你运行内存惊讶。听起来像你需要进一步打破你的问题,或重新考虑架构。 –

+1

我同意@MikeMcCaughan。 60k承诺听起来不合理,可能有更好的解决方案来解决您的问题。 – nils

+0

这并没有太大的意义。如果你有一大串承诺数组,那意味着你的操作已经全部启动了。所以,这里没有一系列的执行。它们已经在并行执行。如果您只是想知道所有承诺何时完成,请说出来,因为这听起来像是真正的问题。现在,在node.js中同时启动60k异步操作几乎没有意义,所以这可能是您真正的问题。我认为你需要备份并向我们展示创建60k承诺的代码。这就是问题所在。 – jfriend00

回答

1

Promise.all()是要检查每个被作为参数传入的并行你的诺言的结果,并在会拒绝第一个错误,或在完成所有承诺后解决。

MDN

Promise.all传递值的之处在于,它是通过迭代对象所有承诺的数组。值的数组维护原始可迭代对象的顺序,而不是承诺解决的顺序。如果在迭代数组中传递的内容不是承诺,则由Promise.resolve将其转换为一个。

如果任何承诺中的任何拒绝,所有承诺立即拒绝承诺的价值拒绝,丢弃所有其他承诺,无论他们是否已经解决。如果传递一个空数组,则该方法立即解决。

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

编辑:

库存在所谓promise-series-node,我认为可以帮助你不少在这里。既然你已经承诺创建的,你可以只通过它您BigArray

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

我个人认为,你的方法用60K +承诺启动不仅会的大量时间,同时也对资源系统执行它们(这就是为什么你的内存不足)。我认为你可能想为应用程序考虑一个更好的体系结构。

EDIT2,什么是一个承诺?:

  1. 未决::启动状态

    甲诺表示结果异步操作的,这可以采取三种状态中的一种的承诺

  2. 实现:成功操作代表的承诺状态
  3. 被拒绝:承诺的状态由失败操作

承诺是一成不变的,一旦他们在履行或拒绝状态。你可以链接promise(很好避免重复的回调),也可以嵌套它们(当关闭时)。网上有很多很棒的文章,here is one I found to be informative

+2

你不“执行承诺”。承诺表示已经启动的异步操作。您无法序列化已经启动的60k异步操作。它们已经在并行运行。所以,目前尚不清楚这有何帮助。 – jfriend00

+0

@ jfriend00通过对这篇文章的所有评论来判断,这里没有任何东西对你有意义。也许你可以发表一个答案并澄清一切。你说承诺不会执行,但是在你的评论中你说他们执行。 –

+1

我无法提供答案,因为这个问题没有意义。真正的答案是可能不会同时启动60k的异步操作,但OP没有向我们展示任何代码,所以我们没有太多的办法来解决真正的问题。 – jfriend00

-1

许诺库bluebird提供称为Promise.map一个辅助方法,它接受一个数组或数组作为它的第一个参数的一个承诺及其所有元素的结果阵列,这反过来也得到promisified映射。也许你可以尝试这样的事:

return Promise.map(BigArray, function(innerArray) { 
    return Promise.all(innerArray); 
}) 
.then(function(finishedArray) { 
    // code after all 60k promises have been resolved comes here 
    console.log("done"); 
}); 

但正如前文所述,这仍然是一个非常耗费资源,可能消耗所有可用的内存激烈的任务。

+0

OP表示他们有一系列承诺。我不清楚Promise.map()如何帮助解决这个问题。 – jfriend00

+0

'map()'将同时解决承诺,但Bluebird的mapSeries()函数是解决OP问题的体面解决方案。 http://bluebirdjs.com/docs/api/promise.mapseries.html – Molomby

+0

@Molomby是的,实际上这是我的意图,我只是错了map()。我认为它会连续执行,但是mapSeries()完成这项工作。感谢您指出了这一点。 – SaSchu

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') 
    } 
    );