2016-04-28 21 views
4

我編寫JavaScript這就需要這些事件順序發生:ES6承諾/調用一個函數的多個履行諾言後(不能使用Promises.all)

  1. 斷火的幾個API調用同時
  2. 一旦所有呼叫完成和響應已返回,執行的代碼行

聽起來簡單,但棘手的問題是,我不能使用Promises.all(),因爲我還是想那行代碼在所有承諾完成之後執行,成功與否。除非我誤解了Promises.all(),否則會導致代碼行不能在then()中執行,並且在error()中執行得太快。

我很可能會漏掉一些明顯的東西,但我可以看到的唯一方法是將API調用承諾鏈接在一起,但這會導致不會一次性觸發它們。所以基本上我認爲我需要一個不是「快速失敗」的Promises.all()版本。

這樣做的正確方法是什麼?

+0

Promise.all()是一個接一個鏈接多個承諾,如果他們有依賴關係。因此,如果一個人失敗,它不會嘗試其他人,並會返回到你的catch()。如果你對拒絕案例(錯誤)有寬容,那麼你應該手動鏈接你的承諾與thens和catches,並通過他們的catch()處理被拒絕的操作並繼續從該catch()的下一個承諾。 – Redu

+0

不確定這是否準確地說它不會「嘗試」其他人:他們都已經開始運行,當他們傳遞給Promise.all時。因此,無論他們擁有什麼樣的行爲,以及任何單獨鏈接到每個鏈接上的.then/catch()操作仍然會運行。 – Dtipson

回答

3

要嚴格使用ES6承諾,您需要將每個承諾包裝在另一個包裝承諾中,當包裝的承諾被履行或拒絕時,承諾會得到解決。

可以是這樣做的:

Promise.all( 
    promises.map(promise => Promise.resolve(promise).catch(_=>_)) 
).then (function () { 
    // All promises finished 
}); 

這假定promises是承諾和/或值的數組。

+0

避免['Promise' constructor antipattern](http://stackoverflow.com/q/23803743/1048572)! – Bergi

+0

@Bergi我不認爲這是一個反模式,當它使事情更具可讀性,但我更新它,以避免使用Promise構造函數。 – Paulpro

+0

除了它沒有,真的:-)順便說一句,你可以簡化更多:'.then(null,_ => _)'或'.catch(_ => _)' – Bergi

0

這可能是一種比這更冷靜的方式,甚至是這種特定方法的更好的書面版本,但是不是使用Promise.all,而是可以將行爲鏈接到每個承諾(對於後者和catch都是如此,這件事更新了主Promise中的一個值。

const allPromises = arrayOfPromises => Promise((resolve,reject)=> { 
    const ln = arrayOfPromises.length, 
     done = 0; 

    const allDone => _ => { 
    if(++done===ln){ resolve(); } 
    } 
    arrayOfPromises.map(p=>p.then(allDone).catch(allDone)); 
});