Native Promise Predicate S2
中文标题:原生 Promise 谓词
- 阶段: Stage 2
- 状态: 进行中
- ECMAScript 版本: —
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案引入了 Promise.isPromise,一个新的谓词,暴露内部 IsPromise 抽象操作的结果,允许无副作用地检测原生 promise。它解决了当前模式如 Promise.resolve(val) === val 的局限性,这些模式会分配不必要的 promise 并可能触发 thenable 同化。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
Promise.isPromise
ECMAScript 提案与规范,关于 Promise.isPromise。
状态
阶段:2
** Champion **:
- Mathieu Hofman (@mhofman) (Agoric)
动机
目前,在没有副作用的情况下检查一个对象是否是原生 promise 是不可能的。通常的做法是测试 Promise.resolve(val) === val,但在否定的情况下,它会创建一个由 val 解析出的新 promise。除了不必要的分配,它还可能触发与 thenable 同化机制 相关的用户代码。
希望进行防御性编程的代码,例如在异步逻辑中处理未知值时避免同步重入,目前只能通过付出一个 tick 的代价(Promise.resolve().then(() => val))来实现,即使该值是安全的原生 promise。
当执行 await val 时,原生 promise 的内部状态会被安全地采用,如果 https://github.com/tc39/ecma262/pull/3689 被接受,对于其他 promise 解析路径也是如此。
instanceof Promise 是不合适的,因为它检查的是 Promise.prototype 是否在值的原型链中,而不是检查该值是否通过了规范内部执行的 IsPromise 检查。
提案
一个新的 Promise.isPromise 谓词,暴露 IsPromise 抽象操作的结果。
先例
Error.isError 对原生 Error 对象做了类似的品牌检查。
膜透明性
与 Error 类似,Promise 也是更适合“通过复制传递”而不是通过膜进行代理的对象。此外,已经可以通过 Promise.resolve() 异步检测一个对象是否是原生 promise。
Promise.isPromise 谓词实际上可以让膜检测那些应该在另一侧重建的 promise 值。