iT邦幫忙

0

【30 天JavaScript 實戰 】 Day 18 |Promise all / race / any / allSettled

2025-12-02 15:10:05217 瀏覽
  • 分享至 

  • xImage
  •  

今日的目標:

  • Promise.all → 全部成功才成功
  • Promise.race → 誰先回來就用誰(timeout 常用)
  • Promise.any → 至少一個成功就成功(備援)
  • Promise.allSettled → 全部做完給你完整報表

真實世界不是只有一個 Promise,
很多時候我們會同時發出好幾個非同步任務。
那要怎麼管理呢?
Promise有一些靜態方法可以使用,能幫我們一次處理多個非同步任務。

1. Promise.all

Promise.all = 全部都要成功,少一個都不行

Promise.all([
  fetch("/api/user"),
  fetch("/api/posts"),
])
  .then(([userRes, postsRes]) => {
    if (!userRes.ok) throw new Error("user API 失敗");
    if (!postsRes.ok) throw new Error("posts API 失敗");

    return Promise.all([userRes.json(), postsRes.json()]);
  })
  .then(([user, posts]) => {
    console.log("user:", user);
    console.log("posts:", posts);
  })
  .catch((err) => {
    console.error("其中一個失敗:", err);
  });
  • 丟進 Promise.all() 的任務會同時執行
  • 其中任何一個 reject → 整個 Promise.all 會直接 reject
  • .then 只會在「全部成功」時執行

實務上的用途

  • 網站首頁同時抓 使用者資料+最新貼文+通知
  • 多張圖片預載入
  • 多個 API 都要成功才能 render 頁面

2. Promise.race

Promise.race = 誰先回來,就聽誰的

做「timeout」的例子:

function timeout(ms) {
  return new Promise((_, reject) => {
    setTimeout(() => reject(new Error("超時")), ms);
  });
}  //建立一個會在幾秒後失敗的 Promise

Promise.race([
  fetch("/api/slow"),
  timeout(3000), // 3 秒沒回應就失敗
])
  .then((res) => {
    if (!res.ok) throw new Error("API 失敗");
    return res.json();
  })
  .then(console.log)
  .catch((err) => {
    console.error("錯誤或超時:", err.message);
  });
  • race 是第一個結束的人
  • 第一個 resolve → 成功
  • 第一個 reject → 失敗
  • 很適合做 API timeout

實務上的用途

  • API 最久只能等 3 秒
  • 圖片載太慢就換 loading 圖
  • 等多個資料來源,看誰先回來

3. Promise.any

Promise.any = 只要有一個成功就好

Promise.any([
  fetch("https://cdn1.example.com/img.png"),
  fetch("https://cdn2.example.com/img.png"),
  fetch("https://cdn3.example.com/img.png"),
])
  .then((res) => {
    console.log("至少有一個成功");
    return res.blob();
  })
  .catch((err) => {
    console.error("全部都失敗:", err);
  });
  • 只要有一個成功 → then
  • 全部都失敗 → catch(收到 AggregateError)

實務上的用途

  • CDN fallback
  • 多伺服器備援
  • 多個 API 來源只要一個成功即可

4. Promise.allSettled

Promise.allSettled = 全部完成後,給狀態報表
也就是說,我們想知道每一件是否有成功、哪一件失敗
這時候不是 只要有一個失敗就整包不行,
我們要的是 完整結果。

Promise.allSettled([
  fetch("/api/a"),
  fetch("/api/b"),
  fetch("/api/c"),
])
  .then((results) => {
    results.forEach((r, i) => {
      if (r.status === "fulfilled") {
        console.log(`第 ${i} 個成功:`, r.value);
      } else {
        console.log(`第 ${i} 個失敗:`, r.reason);
      }
    });
  });
  • 不會因為某一個失敗而中斷
  • 回傳每一個 Promise 的:status(fulfilled / rejected)、value 或 reason

實務上的用途

  • 批次寄信
  • 批次抓很多 API → 就算部分掛掉也要記錄
  • 後台管理系統:檢查大量資料狀態

all / race / any / allSettled 差在哪?

方法 成功條件 失敗條件 什麼時候用
Promise.all 全部成功 任一失敗就失敗 所有資料都要到位
Promise.race 第一個成功就成功 第一個失敗就失敗 timeout、搶最快
Promise.any 任一成功就成功 全部失敗才失敗 CDN、備援來源
Promise.allSettled 全部都會回傳結果 不會 fail 掉整組 統計成功/失敗

圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言