iT邦幫忙

2021 iThome 鐵人賽

DAY 18
0
Modern Web

前端藏寶圖系列 第 18

Promise 方法

今天繼續認識四種 Promise 可以使用的方法,基礎的用法可以先參考昨天的文章

  • Promise.all()
  • Promise.allSettled()
  • Promise.race()
  • Promise.any()

Promise.all()

  • 目的:讓多個 promise 同時執行
  • 參數接受一個可迭代的物件,但通常會傳入 promise 組成的 array 作為参数
  • 每個 promise 完成時,resolve 的值會存入陣列中
  • 所有 promise 都 resolve 才會回傳,但只要有其中一個 promise 被拒絕,則整個 Promise.all 立刻被拒絕
function makeDrinks(drinksName, time) {
  return new Promise((resolve, reject) => {
    if (drinksName.includes("ironman")) {
      reject("ironman冬瓜檸檬賣完了");
    }
    setTimeout(() => {
      resolve(`這是你點的${drinksName}`);
    }, time);
  });
}

// 即使珍珠紅茶的製作時間最長,但並不會影響回傳結果的順序
// 結果的順序會遵循每個 promise 在陣列中的順序
Promise.all([
    makeDrinks("珍珠紅茶", 5000),
    makeDrinks("檸檬愛玉", 1000),
    makeDrinks("多多綠", 0),
    ])
    .then((value) => console.log(value));

//[ '這是你點的珍珠紅茶', '這是你點的檸檬愛玉', '這是你點的多多綠' ]


// 其中一個 promise被拒絕 
Promise.all([
  makeDrinks("珍珠紅茶", 1000),
  makeDrinks("ironman冬瓜檸檬", 2000),
  makeDrinks("檸檬愛玉", 1000),
  makeDrinks("多多綠", 0),
])
  .then((value) => console.log(value))
  .catch((err) => console.log(err));
  
// ironman冬瓜檸檬賣完了

Promise.all() 的失敗優先特點可以運用在當這些非同步事件彼此有相依關係時,只要有一個非同步事件無法成功執行,就立即回傳被拒絕的失敗訊息。

但如果要處理的非同步事件彼此沒有相依關係呢?
這時候就可以思考使用Promise.allSettled()

Promise.allSettled()

MDN 定義: The Promise.allSettled() method returns a promise that resolves after all of the given promises have either fulfilled or rejected, with an array of objects that each describes the outcome of each promise.

  • 也就是說,不管結果是成功或失败,會確認一组非同步事件是否都執行了,並回傳各自的結果
Promise.allSettled([
  makeDrinks("珍珠紅茶", 3000),
  makeDrinks("ironman冬瓜檸檬", 1000),
  makeDrinks("檸檬愛玉", 1000),
  makeDrinks("多多綠", 0),
])
  .then(value => console.log(value))
  .catch(err => console.log(err));
  
//[
//  { status: 'fulfilled', value: '這是你點的珍珠紅茶' },
//  { status: 'rejected', reason: 'ironman冬瓜檸檬賣完了' },
//  { status: 'fulfilled', value: '這是你點的檸檬愛玉' },
//  { status: 'fulfilled', value: '這是你點的多多綠' }
//]  

Promise.race()

  • 和 Promise.all() 雷同,參數接受一個可迭代的物件
  • 任一個 promise 轉變狀態,就回傳一個同樣狀態的 promise 物件,並且接收其成功值或失敗訊息
  • 其餘 promise 的結果或錯誤會被忽略
Promise.race([
  makeDrinks("珍珠紅茶", 3000),
  makeDrinks("檸檬愛玉", 2000),
  makeDrinks("多多綠", 1000),
])
  .then(value => console.log(value))
  .catch(err => console.log(err));
  
// 這是你點的多多綠

Promise.any()

  • 類似Promise.race(),當有一個 promise 完成,就回傳完成結果
  • 當所有 promise 都被拒絕,則會回傳一個特殊物件 AggregateError,會將所有 promise 的失敗訊息存在 errors 屬性中
Promise.any([
  makeDrinks("ironman冬瓜檸檬", 2000),
  makeDrinks("ironman冬瓜檸檬", 2000),
])
  .then((value) => console.log(value))
  .catch((err) => console.log(err.constructor.name, err.errors));
  
// AggregateError ["ironman冬瓜檸檬賣完了", "ironman冬瓜檸檬賣完了"]

小結

如果被這些看似雷同的方法搞得暈頭轉向,可以停下來思考這些方法是為了因應現實世界哪些不同的狀況而出現,或許就能區分它們之間微妙的差異~

參考資料:
MDN
JAVASCRIPT.INFO
Promise 對象


上一篇
Promise
下一篇
初探 AJAX 與 Fetch API
系列文
前端藏寶圖30

尚未有邦友留言

立即登入留言