32
4

2 回答 2

32

那么“thenable”和“promise”这两个术语有什么区别呢?

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

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

到目前为止这么简单。我认为您的实际问题是:“为什么要区分它们?

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

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

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

是的,ECMAScript 规范将这种语法用于内部方法和属性

内部属性的名称用双方括号 [[ ]] 括起来。

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

于 2015-04-03T18:44:07.340 回答
7

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

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

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

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

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

如果规范改为说“如果 x 是一个承诺,那么......”,实施者如何知道是否x是一个承诺?没有实用的方法可以x仅通过检查来确定是否符合 Promise 规范。

一个实现者(比如说,图书馆FooPromises可能会做类似的事情

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

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

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


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

这不是必需的——Resolve不是 Promise 接口的一部分;这只是他们行为的一部分,它非常重要,以至于在文档中被赋予了名称和单独的部分。

于 2015-04-03T15:49:26.953 回答