2016-05-12 69 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') 
    } 
    );