什麼是 Promise.allSettled() !新手老手都要會?

前端小智發表於2021-10-18
作者:Dmitri Pavlutin
譯者:前端小智
來源:dmitripavluti

有夢想,有乾貨,微信搜尋 【大遷世界】 關注這個在凌晨還在刷碗的刷碗智。

本文 GitHub https://github.com/qq449245884/xiaozhi 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

Promise.allSettled() 方法返回一個在所有給定的 promise 都已經 fulfilledrejected 後的 promise,並帶有一個物件陣列,每個物件表示對應的 promise 結果。

接著,我們來看看 Promise.allSettled() 是如何工作的。

1. Promise.allSettled()

Promise.allSettled() 可用於並行執行獨立的非同步操作,並收集這些操作的結果。

該函式接受一個 promise 陣列(通常是一個可迭代物件)作為引數:

const statusesPromise = Promise.allSettled(promises);

當所有的輸入 promises 都被 fulfilledrejected 時,statusesPromise 會解析為一個具有它們狀態的陣列

  1. { status: 'fulfilled', value: value } — 如果對應的 promise 已經 fulfilled
  2. 或者 {status: 'rejected', reason: reason} 如果相應的 promise 已經被 rejected

image.png

在解析所有 promises 之後,可以使用 then 語法提取它們的狀態:

statusesPromise.then(statuses => {
 statuses; // [{ status: '...', value: '...' }, ...]
});

或者使用 async/await 語法:

const statuses = await statusesPromise;
statuses; // [{ status: '...', value: '...' }, ...]

2. 取水果和蔬菜

在深入研究 Promise.allSettle() 之前,我們先定義兩個簡單的 helper 函式。

首先,resolveTimeout(value, delay)返回一個 promise ,該 promise 在經過 delay 時間後用 value 來實現

function resolveTimeout(value, delay) {
  return new Promise(
    resolve => setTimeout(() => resolve(value), delay)
  );
}

第二,rejectTimeout(reason, delay) - 返回一個 promise,在經過 delay 時間後拒絕reason

最後,我們使用這些輔助函式來試驗 promise.allsettle()

2.1 All promises fulfilled

我們同時訪問當地雜貨店的蔬菜和水果。訪問每個列表是一個非同步操作:

const statusesPromise = Promise.allSettled([
  resolveTimeout(['potatoes', 'tomatoes'], 1000),
  resolveTimeout(['oranges', 'apples'], 1000)
]);
// wait...
const statuses = await statusesPromise;
// after 1 second
console.log(statuses); 
// [
//   { status: 'fulfilled', value: ['potatoes', 'tomatoes'] },
//   { status: 'fulfilled', value: ['oranges', 'apples'] }
// ]

線上事例:https://codesandbox.io/s/all-...

Promise.allSettled([...])返回一個 promise statusesPromise,該 promise 在1秒內解決,就在蔬菜和水果被解決之後,並行地解決。

statusesPromise 解析為一個包含狀態的陣列。

  1. 陣列的第一項包含有蔬菜的已完成狀態:status: 'fulfilled', value: ['potatoes', 'tomatoes'] }
  2. 同樣的方式,第二項是水果的完成狀態: { status: 'fulfilled', value: ['oranges', 'apples'] }

2.2一個 promise 被拒絕

想象一下,在雜貨店裡已經沒有水果了。在這種情況下,我們拒絕水果的 promise。

promise.allsettle() 在這種情況下如何工作?

const statusesPromise = Promise.allSettled([
  resolveTimeout(['potatoes', 'tomatoes'], 1000),
  rejectTimeout(new Error('Out of fruits!'), 1000)
]);
// wait...
const statuses = await statusesPromise;
// after 1 second
console.log(statuses); 
// [
//   { status: 'fulfilled', value: ['potatoes', 'tomatoes'] },
//   { status: 'rejected', reason: Error('Out of fruits!') }
// ]

線上事例:https://codesandbox.io/s/one-...

Promise.allSettled([...]) 返回的 promise 在 1 秒後解析為一個狀態陣列:

  1. 陣列的第一項,蔬菜 promise 成功解析:{ status: 'fulfilled', value: ['potatoes', 'tomatoes'] }
  2. 第二項,因為水果 promise 被拒絕,所以是一個拒絕狀態: { status: 'rejected', reason: Error('Out of fruits') }

即使輸入陣列中的第二個 promise 被拒絕,statusesPromise仍然會成功解析一個狀態陣列。

2.3 所有的 promises 都被 rejected

如果雜貨店裡的蔬菜和水果都賣光了怎麼辦?在這種情況下,兩個 promise 都會被拒絕。

const statusesPromise = Promise.allSettled([
  rejectTimeout(new Error('Out of vegetables!'), 1000),
  rejectTimeout(new Error('Out of fruits!'), 1000)
]);
// wait...
const statuses = await statusesPromise;
// after 1 second
console.log(statuses); 
// [
//   { status: 'rejected', reason: Error('Out of vegetables!')  },
//   { status: 'rejected', reason: Error('Out of fruits!') }
// ]

線上事例:https://codesandbox.io/s/all-...

在這種情況下,statusesPromise仍然成功地解析為一個狀態陣列。然而,該陣列包含被拒絕的promise 的狀態。

3.總結

Promise.allSettled(promises)可以並行地執行 promise,並將狀態(fulfilled 或reject)收集到一個聚合陣列中。

Promise.allSettled(...)在你需要執行平行和獨立的非同步操作並收集所有結果時非常有效,即使某些非同步操作可能失敗。

~~ 完,我是刷碗智,你們的點贊及在看是對我刷碗最大的認可。

編輯中可能存在的bug沒法實時知道,事後為了解決這些bug,花了大量的時間進行log 除錯,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug


原文:https://dmitripavlutin.com/pr...

交流

文章每週持續更新,可以微信搜尋【大遷世界 】第一時間閱讀,回覆【福利】有多份前端視訊等著你,本文 GitHub https://github.com/qq449245884/xiaozhi 已經收錄,歡迎Star。

相關文章