Symbol.thenable ?
- 阶段: 未分阶段
- 状态: 已撤回
- ECMAScript 版本: —
- 同步时间: 2026年8月26日
- English original · 官方仓库
该提案引入了 Symbol.thenable 以防止 Promise.resolve 将某些对象视为 thenable,特别是动态导入时的模块命名空间对象。它解决了模块命名空间被错误解释为 thenable 时可能出现的意外行为。resolve 中白名单化模块命名空间对象的替代方案。
以下 README 来自上游仓库,其中的阶段或状态标注可能滞后;当前信息以提案概览为准。
Symbol.thenable
Champions: Myles Borins, Jordan Harband
Author: Gus Caplan
Stage 0
为什么
Promise.resolve 的行为包括检查你传递给它的任何对象的 then 函数。这允许与遗留的第三方 Promise 实现协议进行互操作,在大多数情况下不会导致任何问题,但仍然存在一些不必要的场景。
这在动态导入模块命名空间对象时尤其如此,这很快将成为语言规范的一部分。命名空间可能被解释为"thenable",导致 import() 返回非命名空间对象——这可能非常出乎意料。之前围绕这些场景进行了大量讨论,包括
https://github.com/tc39/proposal-dynamic-import/issues/47 和
https://github.com/tc39/proposal-dynamic-import/issues/48。
提案
对此问题的自然结论是为对象添加某种修饰符,使得 Promise.resolve 知道不应执行"thenable"行为。
引入:Symbol.thenable
此外,此符号将默认设置在模块命名空间对象上。虽然用户已经可以通过 Promise 解析来 import * 一个命名空间对象并返回它,但今天这仍然可以被认为是非常罕见的情况。
这源于尝试思考该问题的最通用解决方案。替代方案可能包括在 Promise.resolve 中显式地将模块命名空间对象列入黑名单,但对此存在阻力,因为可能不完全直观为什么这个对象要被区别对待。Symbol.thenable 为此提供了清晰的解释。
将来,此符号还可以被协议使用(参见 第一类协议提案),沿着 Promise.Thenable 的思路作为一种"禁用"符号。
替代方案和选项
-
将符号挂载在
Promise命名空间上(Promise.thenable) -
将我们不想视为"thenable"的特定对象列入白名单: