喜好就拿去用吧,關於一些常用程式碼的記錄
阿新 • • 發佈:2021-10-24
首個成功的Promise
從一組Promise裡面得到第一個“成功的”結果,同時獲得了併發執行的速度和容災的能力。
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,實現提前退出!太巧妙了!
這個方法適合的場景:
- 有多條路可以走,其中任意一條路走通即可,其中有一些路失敗也沒關係
- 為了加速得到結果,併發地走多條路,避免瀑布式嘗試
參考自 https://stackoverflow.com/a/3...
2020年8月28日更新:現在它已經被新版瀏覽器原生實現:Promise.any
非同步reduce
有時候業務邏輯要求我們必須序列地 處理多個數據,茉莉花程式碼不能像上面那樣併發地處理多個數據。即,通過瀑布式的非同步操作,將一個數組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 () => {
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)
})
}
})()
- 兩個方案相同點:對每個陣列項執行處理,並且其中任一次處理的失敗都會造成整體失敗
- reduce方案是瀑布式的,map方案是併發的
- reduce方案,當你處理到第n項的時候,你可以使用之前的累積量