Promise.try S4
- 阶段: Stage 4
- 状态: 已完成
- ECMAScript 版本: ES2025
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案引入了 Promise.try,一个调用函数并返回 promise 的方法,通过 promise 语义处理同步返回值或抛出的异常。它避免了 Promise.resolve().then(f) 的额外微任务延迟,镜像了 async function 到第一个 await 的执行。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
Promise.try
ECMAScript 提案、规范和 Promise.try 的参考实现
规范由 @ljharb 起草。
理由
我和许多其他人都有一个常见的用例:我有一个函数 f。这个函数可能是异步的,返回一个 Promise,也可能不是——我不想必须知道。然而,我想把它包装在一个 Promise 中,这样如果它 是 异步的,或者它抛出了异常,我就可以依靠 Promise 语义和 .catch 来处理它。
在 JS Promises 中实现这一点的典型“易于记忆”的方式是 Promise.resolve().then(f)。这很有效!它会捕获任何抛出的异常,并将函数返回的任何 thenable 或值包装成 Promise。但是,f 会被不必要地异步运行,在未来的一个 tick 中执行。
如果我想要 f 在同一个 tick 中运行——因为毕竟它可能同步返回一个值——或者如果我想要与 async function 在第一个 await 之前具有并行语义——那么我需要使用 new Promise(resolve => resolve(f()))。这达到了我的目标,但写起来不人性化,也不容易记住。
使用 Promise.try(f),我可以获得与上面那堆 new Promise 相同的语义,很好地镜像 async function,允许乐观地同步但安全地执行函数,并且之后能够使用 Promise。耶!
用户态实现
p-try包(每周 4400 万次下载,总下载量 89 亿次;备用链接)- Bluebird:
Promise.try/Promise.attempt- 接受一个函数,不带参数调用它。 - Q:
Q.try/Promise.prototype.fcall-Q.try接受一个函数,不带参数调用它。Promise#fcall已弃用,但接受一个参数列表,并使用该参数列表调用给定的函数。 - when:
when.try/when.attempt- 接受一个函数和一个可选的参数列表,并使用该参数列表调用给定的函数。 - ES6:
es6-promise-try- 接受一个函数,不带参数调用它。功能上等同于 Bluebird 的Promise.try,但使用 ES6 Promises 的独立实现。 - dojo/when
进一步阅读
- http://cryto.net/~joepie91/blog/2016/05/11/what-is-promise-try-and-why-does-it-matter/
- https://twitter.com/RReverser/status/695678489937186816
命名
最常见的名称是 try,它与语法上的 try 块有清晰的平行关系。常见的替代名称是 attempt,但这主要是为了 ES3 兼容性,这里不需要。
规范
您可以查看以 HTML 形式呈现的规范。
Polyfills
- core-js v3.37+(文档)
- es-shims: promise.try