海量编程文章、技术教程与实战案例

网站首页 > 技术文章 正文

Promise.resolve(func())不够用?为何推出 Promise.try()?

yimeika 2025-06-23 22:49:39 技术文章 1 ℃

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!

在 Web 上执行异步任务并不简单,但 Web 上的异步任务又无处不在。无论是 fetch 调用还是其他异步操作,当内置方法提供强大的错误处理时,浏览器会让开发者更轻松,例如:使用 then、catch 和 finally 方法,Promise 已经默认提供了此功能。

即便如此,开发者构建应用程序的方式应该足够灵活,而且在应用程序中执行的所有操作不一定都是异步的。有时,可能希望以一种更简单的方式来处理回调的结果,而传递给 Promise 的回调是否同步并不重要。

Promise.try 是一种目前所有主流浏览器引擎都可用的方法,其为开发者简化了这一过程,而且是 Baseline 中新推出的功能。

1.Promise.resolve 无法捕获的异常

比如下面 Promise.resolve 中的 syncErrorFunc 函数抛出的 同步错误 将不会被正常捕获:

// Promise.resolve 错误无法被捕获
const syncErrorFunc = () => {
  throw new Error("这是一个同步抛出的错误!");
};
const faultyPromise = Promise.resolve(syncErrorFunc())
  .then((result) => console.log("成功:", result))
  .catch((error) => {
    console.error("这里永远不会被执行:", error);
  });

当然,也包括 异步错误,比如:

const asyncSafePromise = Promise.resolve(
  new Promise(resolve => {
    setTimeout(() => {
      throw new Error('异步错误');
    }, 100);
  })
).catch((e)=>{
  console.error(e);
});

2. 为什么需要 Promise.try

如上文所述,开发者经常有一个接受同步或异步的 API,同时希望通过将结果包装在 Promise 中来统一处理。

最直接的方法是 Promise.resolve(func()),问题是:如上文所述,如果 func() 抛出同步错误, 则该错误不能被捕获并转换为已拒绝的 Promise。

开发者常见的方法通常如下所示:

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

但是 Promise.try 则更加清晰:

Promise.try(func);

同时结合 Promise.try,开发者还可以继续正常使用 then、catch 和 finally 方法处理 Promise 的 resolve 或 reject:

Promise.try(callback)
  .then((result) => console.log(result))
  .catch((error) => console.log(error))
  .finally(() => console.log("All settled."));

指的一提的是,如果使用的是 async/await 语法,则不要使用 Promise.try,而建议使用 try/catch/finally 块。

与此同时,如果回调函数有参数,开发者可以用以下两种方法处理:

// 相当于创建了一个闭包处理
Promise.try(() => callback(param1, param2));
// 该方式不用创建闭包也能处理
Promise.try(callback, param1, param2);

使用 Promise.try 的主要好处是, 无论传递的回调是同步还是异步,其都可以让开发者统一使用 Promise。这对于将 callback 传递给 Promise 的工具函数,使用 Promise.try 可确保传递给其的任何回调都能得到正确的错误处理。

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");
});

目前, Promise.try 已达到 Baseline 级别,开发者能够在所有主流浏览器引擎中使用。随着时间的推移,很快将能够在 Web 应用程序中使用,并逐渐成为 Web 平台稳定且可互操作的一部分。

Baseline:指某个特性的最低版本要求,意味着从该版本开始,所有后续版本都将支持这一特性。

参考资料

https://web.dev/blog/promise-try-baseline

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/try

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve

Tags:

最近发表
标签列表