Promise.withResolvers()

Baseline 2024
新推出

自 ⁨2024 年 3 月⁩ 起,此功能可在最新的裝置和瀏覽器版本上執行。此功能可能不適用於較舊的裝置或瀏覽器。

Promise.withResolvers() 靜態方法返回一個物件,該物件包含一個新的 Promise 物件,以及兩個用於解析或拒絕它的函式,這對應於傳遞給 Promise() 建構函式的執行器的兩個引數。

語法

js
Promise.withResolvers()

引數

無。

返回值

一個包含以下屬性的普通物件

promise

一個 Promise 物件。

resolve

一個解析該 Promise 的函式。有關其語義,請參閱 Promise() 建構函式參考。

reject

一個拒絕該 Promise 的函式。有關其語義,請參閱 Promise() 建構函式參考。

描述

Promise.withResolvers() 完全等同於以下程式碼

js
let resolve, reject;
const promise = new Promise((res, rej) => {
  resolve = res;
  reject = rej;
});

只是它更簡潔,並且不需要使用 let

使用 Promise.withResolvers() 的主要區別在於,解析和拒絕函式現在與 Promise 本身存在於同一作用域中,而不是在執行器中建立並僅使用一次。這可能啟用一些更高階的用例,例如在重複使用它們來處理週期性事件時,尤其是在流和佇列中。這通常也比將大量邏輯包裝在執行器內導致更少的巢狀。

Promise.withResolvers() 是通用的,並且支援子類化,這意味著它可以被呼叫在 Promise 的子類上,並且結果將包含子類型別的 Promise。要做到這一點,子類的建構函式必須實現與 Promise() 建構函式相同的簽名——接受一個單獨的 executor 函式,該函式可以與 resolvereject 回撥函式作為引數一起呼叫。

示例

將流轉換為非同步可迭代物件

Promise.withResolvers() 的用例是當您有一個 Promise 需要由無法包裝到 Promise 執行器內的事件監聽器來解析或拒絕時。以下示例將 Node.js 的 可讀流 轉換為 非同步可迭代物件。這裡的每個 promise 代表一個可用資料的批次,每次讀取當前批次時,都會為下一批資料建立一個新的 Promise。請注意,事件監聽器僅被附加一次,但每次實際呼叫不同的 resolvereject 函式版本。

js
async function* readableToAsyncIterable(stream) {
  let { promise, resolve, reject } = Promise.withResolvers();
  stream.on("error", (error) => reject(error));
  stream.on("end", () => resolve());
  stream.on("readable", () => resolve());

  while (stream.readable) {
    await promise;
    let chunk;
    while ((chunk = stream.read())) {
      yield chunk;
    }
    ({ promise, resolve, reject } = Promise.withResolvers());
  }
}

在非 Promise 建構函式上呼叫 withResolvers()

Promise.withResolvers() 是一個通用方法。它可以被呼叫在實現與 Promise() 建構函式相同簽名的任何建構函式上。例如,我們可以將其呼叫在一個建構函式上,該建構函式將 console.log 作為 resolvereject 函式傳遞給 executor

js
class NotPromise {
  constructor(executor) {
    // The "resolve" and "reject" functions behave nothing like the native
    // promise's, but Promise.withResolvers() just returns them, as is.
    executor(
      (value) => console.log("Resolved", value),
      (reason) => console.log("Rejected", reason),
    );
  }
}

const { promise, resolve, reject } = Promise.withResolvers.call(NotPromise);
resolve("hello");
// Logs: Resolved hello

規範

規範
ECMAScript® 2026 語言規範
# sec-promise.withResolvers

瀏覽器相容性

另見