【问题标题】:Regarding Promises/A+ Specification, what is the difference between the terms "thenable" and "promise"?关于 Promises/A+ 规范,“thenable”和“promise”这两个术语有什么区别?
【发布时间】:2015-06-08 17:24:04
【问题描述】:

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

关于第 1 节。术语,

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

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

那么"thenable""promise"这两个术语有什么区别?

也在第 2.3 节中。承诺解决程序,

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

所以我的问题是:

为什么用两个左括号和右括号表示?有什么约定吗?

非常感谢。

【问题讨论】:

    标签: javascript promise specifications specification-pattern


    【解决方案1】:

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

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

    promise 解析过程是一个抽象操作,将 promise 和 value 作为输入,我们将其表示为[[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 接口的一部分;这只是他们行为的一部分,它非常重要,以至于在文档中被赋予了名称和单独的部分。

    【讨论】:

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

    那么“thenable”和“promise”这两个词有什么区别?

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

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

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

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

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

    为什么用两个左括号和右括号表示?有什么约定吗?

    是的,ECMAScript 规范将这种语法用于internal methods and properties

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

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

    【讨论】:

    • 非常好的答案。从规范中展示 thenable 是多么不可信的例子可能会很好 - 规范防范 getter、抛出的 thenable、吸收抛出的 thenable 的 thenable 等等。
    • 我没有从 Promise A+ 规范中找到 thenable 的 then 方法的要求。如果必须从中返回承诺等。规范对此有点不清楚。
    • @MikaelLepistö Promises/A+ 规范不假定关于 thenables 的任何事情(他们的then 方法通过两个回调调用,并且预计至少回调其中一个至少一次)它只说明了then 承诺方法的要求。
    • 对于具有 then 方法但不打算用作 promise 的对象是否存在已知问题?
    • @jinbeomhong 是的,它已经发生了几次,例如heretherewith module exports。然而,总的来说,人们很快就学会了不再使用自定义的then 方法。
    猜你喜欢
    • 2019-04-20
    • 1970-01-01
    • 2019-05-22
    • 2011-09-22
    • 1970-01-01
    • 2017-04-29
    • 2012-01-01
    • 1970-01-01
    • 2016-04-16
    相关资源
    最近更新 更多