关于 Promises/A+ 规范,术语“thenable”和“promise”之间有什么区别?

IT技术 javascript promise specifications specification-pattern
2021-02-03 10:49:24

我正在查看“Promises/A+”规范,但无法理解以下内容:

关于第 1 节术语,

1.1. "promise”是具有 then 方法的对象或函数,其行为符合本规范。

1.2. “thenable”是定义 then 方法的对象或函数。

那么术语"thenable"之间有什么区别"promise"

同样在第 2.3 节中。Promise解决程序,

Promise解析过程是一个抽象操作,将Promise和值作为输入,我们将其表示为[[Resolve]](promise, x)

所以我的问题是:

为什么它在 2 个左括号和右括号内表示?有什么约定吗?

非常感谢你。

2个回答

那么术语“thenable”和“promise”之间有什么区别?

我认为您已经引用的部分确实很好地回答了这个问题:

  • 一个 thenable 是一个带有then方法的对象任何对象。
  • 一个promise 是一个具有符合规范then方法(即thenable)的对象

到目前为止如此简单。我认为你的实际问题是:“他们为什么与众不同?

问题在于,通过查看一个对象,您无法确定它是否是一个Promise。
可能会说它是一个 Promise,因为您可以看到它的then方法是由您自己或您信任的人实现的——通常是您选择的 Promise 库。您将能够“看到”这一点,因为该对象确实从您的 promise 原型继承,或者您甚至可以将方法(在引用上)与您定义的函数进行比较。或任何其他对您来说足够的检查方法。
可能会说它不是Promise,因为它没有then方法。
但是你如何处理一个实现了then但不知道是Promise的对象呢?这是一个可以, 并将按此处理。

Promises/A+ 规范旨在实现 Promise 实现之间的互操作性,并使用鸭子类型.then()方法的存在它确实指定了关于如何处理此类 thenables(可能是Promise或至少具有类似行为)的精确算法,以便您可以从它们创建实际的、可信的(“已知”)Promise。

为什么它在 2 个左括号和右括号内表示?有什么约定吗?

是的,ECMAScript 规范对内部方法和属性使用以下语法

内部属性的名称括在双方括号 [[ ]] 中。

这些属性实际上并不需要存在,它们纯粹用于描述应该发生的事情——一个实现必须使用它们一样行事不过,它们是完全抽象的操作。

是否存在关于具有 then 方法但不打算用作Promise的对象的已知问题?
2021-03-12 10:49:24
@MikaelLepistö的Promise/ A +规格不承担任何关于thenables(他们的then方法被调用两次回调,预计给他们打电话的至少一回至少一次)只规定了要求thenPromise的方法。
2021-03-13 10:49:24
非常好的答案。从规范中展示 thenable 是多么不可信的例子可能会很好 - 规范防止 getter、抛出的 thenable、同化抛出的 thenable 的 thenable 等等。
2021-03-27 10:49:24
@jinbeomhong 是的,它发生过几次,例如在这里那里module导出然而,一般来说,人们很快就学会了不再使用自定义then方法。
2021-04-05 10:49:24
我没有从 Promise A+ 规范中找到thenthenable 方法的要求。如果必须从它返回Promise等,规范对此有点不清楚。
2021-04-06 10:49:24

这是一个聪明的尝试,可以让 Promise 在不同的库之间更容易互操作。

规范thenable仅在几个地方使用了该术语这是最重要的(empasis 我的):

Promise解析过程是一个抽象操作,将Promise和值作为输入,我们将其表示为[[Resolve]](promise, x)如果 x 是一个 thenable,它会尝试让 promise 采用 x 的状态,假设 x 的行为至少有点像 promise。否则,它以值 x 履行Promise。

这将使实现者进行如下检查:

if (typeof(x.then) === 'function') {
    // adopt the state of x
} else {
    // fulfill promise with value x
}

如果规范改为说“如果 x 是一个Promise,那么...”,实现者如何知道是否x是一个Promise?没有切实可行的方法来确保x仅通过检查它是否符合 Promise 规范。

一个实现者(比如,库FooPromises可能会做类似的事情

if (x instanceof FooPromises.Promise) {
    // adopt the state of x
} else {
    // fulfill promise with value x
}

它会有效地拒绝来自不同实现的任何Promise。

相反,通过thenable在这种情况下使用实现者可以轻松验证的超简单定义,进行此检查是微不足道的,并且您可以使实现相互配合。


对于你的第二个问题,我不确定,但我的想法是一个符号[[Resolve]](promise, x)强调它是一个抽象操作。如果他们去掉括号而只说Resolve(promise, x),这会以某种方式暗示实现者应该创建一个真正的函数命名Resolve并公开它。

这不是必需的 -Resolve不是Promise界面的一部分;这只是他们行为的一部分,非常重要,以至于在文档中给了它一个名称和一个单独的部分。

你也知道为什么用 2 个括号来表示Promise解决程序吗?它们表示函数还是回调?它遵循哪些约定?谢谢你。
2021-03-15 10:49:24
谢谢你的澄清。所以 thenable 是任何具有“then”功能的东西,promise 是一种特殊的 thenable,据我所知,它符合规范。
2021-03-18 10:49:24
那么 thenable 和 promise 有什么区别呢?您如何定义差异?
2021-03-22 10:49:24
它们表示规范的一部分,而不是任何特定于 Javascript 的内容。括号在那里,所以它Resolve不像函数或回调。
2021-03-29 10:49:24
如果我创建一个 object var foo = {'then': function() { alert(123) }};,那么它是一个 thenable 但显然不是一个Promise。
2021-03-31 10:49:24