從一組Promise裏面獲得第一個「成功的」結果,同時得到了併發執行的速度和容災的能力。api
Promise.race
不知足需求,由於若是有一個Promise reject,結果Promise也會當即reject;
Promise.all
也不知足需求,由於它會 等待全部Promise,而且要求全部Promise都成功resolve。
function firstSuccess(promises){ return Promise.all(promises.map(p => { // If a request fails, count that as a resolution so it will keep // waiting for other possible successes. If a request succeeds, // treat it as a rejection so Promise.all immediately bails out. return p.then( val => Promise.reject(val), err => Promise.resolve(err) ); })).then( // If '.all' resolved, we've just got an array of errors. errors => Promise.reject(errors), // If '.all' rejected, we've got the result we wanted. val => Promise.resolve(val) ); }
把resolve的Promise反轉成reject,把reject的Promise反轉成resolve,而後用Promise.all
合併起來。
這樣的話,只要有一個原始Promise成功resolve,就會形成Promise.all
馬上被reject,實現提早退出!太巧妙了!數組
這個方法適合的場景:promise
參考自 https://stackoverflow.com/a/3...併發
有時候業務邏輯要求咱們必須串行地處理多個數據,不能像上面那樣併發地處理多個數據。即,經過瀑布式的異步操做,將一個數組reduce成一個值。這個時候能夠巧妙地使用array.reduce:異步
(async () => { const data = [1, 2, 3] const result = await data.reduce(async (accumP, current, index) => { // 後面的處理要等待前面完成 const accum = await accumP; const next = await apiCall(accum, current); return next }, 0); console.log(result) // 6 async function apiCall(a, b) { return new Promise((res)=> { setTimeout(()=> {res(a+b);}, 300) }) } })()
與更常見的【array.map + Promise.all方案】對比:async
(async () => { const data = [1, 2, 3] const result = await Promise.all( data.map(async (current, index) => { // 處理是併發的 return apiCall(current) }) ) console.log(result) async function apiCall(a) { return new Promise((res) => { setTimeout(() => { res(a * 2) }, 300) }) } })()
參考自 https://stackoverflow.com/a/4...code