Promise.try()

实验性: 这是一个 实验性技术
在生产环境中使用此功能前,请仔细查看 浏览器兼容性表

Promise.try() 静态方法接受任何类型的回调(同步或异步返回或抛出),并将结果包装在 Promise 中。

语法

js
Promise.try(func)

参数

func

一个同步调用且没有参数的函数。它可以执行任何操作——返回一个值、抛出一个错误或返回一个 Promise。

返回值

一个 Promise,它

  • 如果 func 同步返回一个值,则已完成。
  • 如果 func 同步抛出一个错误,则已拒绝。
  • 如果 func 返回一个 Promise,则异步完成或拒绝。

描述

您可能有一个采用回调的 API。回调可能是同步的或异步的。您希望通过将结果包装在 Promise 中来统一处理所有内容。最直接的方法可能是 Promise.resolve(func())。问题是,如果 func() 同步抛出一个错误,则不会捕获此错误并将其转换为已拒绝的 Promise。正确的做法如下,Promise.try(func) 与之完全等效

js
new Promise((resolve) => resolve(func()));

除了 Promise.try() 可能更简洁易读之外。更准确地说,以下是 Promise.try() 实现的更忠实的表示(尽管它仍然不应作为 polyfill 使用)

js
new Promise((resolve, reject) => {
  try {
    resolve(func());
  } catch (error) {
    reject(error);
  }
});

对于内置的 Promise() 构造函数,从执行器抛出的错误会自动捕获并转换为拒绝,因此这两个示例是等效的。

请注意,Promise.try() 等效于此,尽管非常相似

js
Promise.resolve().then(func);

区别在于传递给 then() 的回调始终异步调用,而 Promise() 构造函数的执行器同步调用。Promise.try 也会同步调用该函数,并在可能的情况下立即解析 Promise。

Promise.try() 结合 catch()finally(),可以用于在一个链中处理同步和异步错误,并使 Promise 错误处理看起来几乎像同步错误处理。

示例

使用 Promise.try()

以下示例接受一个回调,“提升”到 Promise 中,处理结果并进行一些错误处理

js
function doSomething(action) {
  return Promise.try(action)
    .then((result) => console.log(result))
    .catch((error) => console.error(error))
    .finally(() => console.log("Done"));
}

doSomething(() => "Sync result");

doSomething(() => {
  throw new Error("Sync error");
});

doSomething(async () => "Async result");

doSomething(async () => {
  throw new Error("Async error");
});

在 async/await 中,相同的代码如下所示

js
async function doSomething(action) {
  try {
    const result = await action();
    console.log(result);
  } catch (error) {
    console.error(error);
  } finally {
    console.log("Done");
  }
}

在非 Promise 构造函数上调用 try()

Promise.try() 是一个泛型方法。它可以在任何实现与 Promise() 构造函数相同签名的构造函数上调用。例如,我们可以将其调用在一个将 console.log 作为 resolvereject 函数传递给 executor 的构造函数上

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

const p = Promise.try.call(NotPromise, () => "hello");
// Logs: Resolved hello

const p2 = Promise.try.call(NotPromise, () => {
  throw new Error("oops");
});
// Logs: Rejected Error: oops

规范

规范
Promise.try
# sec-promise.try

浏览器兼容性

BCD 表仅在启用 JavaScript 的浏览器中加载。

另请参阅