2016-08-07 47 views
1

目前,此代碼打印出一個零,因爲數組中的第一個承諾立即解決。如何處理承諾,因爲他們解決?

const promises = []; 
 
const promiser = (number) => new Promise((resolve, reject) => window.setTimeout(() => resolve(number), number * 100)); 
 
for (let index = 0; index < 10; index++) { 
 
    const promise = promiser(index); 
 
    promises.push(promise); 
 
} 
 

 
Promise.race(promises).then(r => console.debug(r));

我期待讓這個曾經最快的承諾解決,它是從promises數組中刪除和新Promise.race調用,其餘的承諾提出,重複操作,直至無承諾離開了。

由於Promise.race返回承諾的結果,而不是解決的承諾本身,但是,我無法確定哪個承諾是解決的,我不知道哪一個從數組中刪除。有沒有辦法知道這個?我想我可以用某種相關鍵和結果返回一個複雜的對象,但這似乎很奇怪。我希望Promise.race回調的第二個參數是承諾的索引,但事實並非如此,因爲then只是另一個承諾的then,所以它如何知道它應該返回一些無論如何索引。你能想出更好的方法嗎?

另外,我運行了第一個race的所有承諾,但這對後續的race不應該是個問題,對吧?如果在後續的race調用之前解決了另一個承諾,它應該只是返回它,沒問題,對不對?如果同時解決了多個承諾,它只會返回第一個(按陣列順序或按照分辨率順序?),然後下一個race會返回第二個,等等......對吧?

順便說一句我也儘管我可以走陣列並刪除isResolved的承諾,但那不是真的。不過,即使這樣,對於race調用之間的多個承諾解決的情況,這種情況也會徹底破壞。

+1

你可以讓Promises解決一個值,該值標識承諾,以及你之後的價值 - 就你的例子而言,你的價值就是索引,所以做你想做的事情是很微不足道的。代碼 –

+0

承諾。當你只關心其中一個決議時使用race()。 - 對於順序執行,只需將.then()子句添加到單個承諾中,也可以返回一個承諾。然後 - 對於並行執行,使用Promise.all在Mattias Buelens中回答 –

回答

1

,如果你是一個承諾庫如bluebird你可以找到一些工具,可以幫助你組織你的代碼更優秀(如Promise.reducePromise.any)工作,就可以返回一個標識符的承諾

const promises = []; 
const promiser = (number, id) => new Promise((resolve, reject) => window.setTimeout(() => resolve({ number, id }), number * 100)); 
for (let index = 0; index < 10; index++) { 
    const promise = promiser(index, "id_" + index); 
    promises.push(promise); 
} 

Promise.race(promises).then(r => console.debug(r.id)); 

不管怎麼說

+0

謝謝,基本上我所說的在中段。這很糟糕,因爲我不能用我沒有創建的承諾來使用它。我會看看藍鳥,看看它是否適合我的需求。 –

+2

您可以使用它與您不創建的承諾,通過使用'.then(r =>({result:r,id:someIdentifier})))'的行 - 並且這是您在陣列 –

+1

好點!順便說一句,@drinchev Bluebird似乎按順序運行'each'和'reduce',這很糟糕,因爲對我來說,承諾解決的順序並不重要,我需要儘快處理每一個。但是,ID和@Jaromanda X提議的技巧將適用於我,再次感謝。 –

4

我期待讓這個曾經最快的承諾解決,它是從promises數組中刪除和新Promise.race調用,其餘的承諾提出,重複操作,直至無承諾離開了。

你爲什麼要使用Promise.race,如果你最終想要處理所有的承諾?你能不能簡單地處理每一個承諾,只要它解決了,然後等到所有的承諾都被處理了?

const promises = []; 
const promiser = (number) => new Promise((resolve, reject) => window.setTimeout(() => resolve(number), number * 100)); 

for (let index = 0; index < 10; index++) { 
    const promise = promiser(index) 
     .then(r => process(r)); // process every promise individually 
    promises.push(promise); 
} 

Promise.all(promises) // wait for all promises to be processed 
     .then(r => console.debug('all done!')); 

還是process異步的,你需要確保只有一個承諾是在同一時間得到處理?

+0

最初,我想'進程'也是異步的,所以是的,但是當我正在進一步研究我的問題時,事實證明我可以在沒有它的情況下做到這一點,所以你確實是對的!如果你不介意的話,我會保留@ drinchev的答案,因爲他們回答我的問題,但是你幫助我看到我問的是錯誤的問題。謝謝。 –

+0

這是正確的答案。 - for循環中的3行應該是單個推式表達式 - 應該將.catch添加到Promise.all()。then()的末尾,以獲得第一個拒絕或異常。 –