当一个Promise被多次解决时会发生什么?

8
如果ES6 Promise被拒绝/解决多次,标准行为是什么?
以下代码在Google Chrome中只被解决了一次,这是所有浏览器中的标准行为吗?
new Promise(function(e) {
    $('#button').click(function(){
        resolve();
    });
});

我曾看到一个promise polyfill在尝试解决已经解决的promise时抛出异常。es6-promise规范是否指定了这一点,还是该polyfill不符合标准? 更新 抱歉,我刚意识到它不是一个polyfill,而只是一个Promise的最小实现(非标准)。

答案的要点是,不要使用那个未命名的 polyfill,因为它不是“标准”的。 - Jaromanda X
1
你确定你看到的 Promise 库是一个 polyfill 吗?在 ES2015 标准将 Promise 内置到 JavaScript 之前,有多个 Promise 库存在。 - T.J. Crowder
2个回答

11

我可以为您翻译:

一个 promise 只能被解决或 settled 一次。一旦 promise 被解决、履行或拒绝,后续的 resolve 或 settle 调用会被忽略。(如果这些术语不熟悉或只有模糊的印象,我在 我的博客上 写了关于 promise 术语的内容。) 不会引发错误。

我看到一个 promise polyfill 在尝试解决已经解决的 promise 时抛出异常。 es6-promise 的规范是否指定了这个问题...?

没有。这在 promise 解决函数 中有所涵盖,它说明了它们的功能。以下是前几个步骤:

当一个Promise的resolve函数被调用并传入参数resolution时,将执行以下步骤:
  1. F成为活动函数对象。
  2. 断言: F有一个[[Promise]]内部插槽,其值是一个对象。
  3. promise成为F.[[Promise]]。
  4. alreadyResolved成为F.[[AlreadyResolved]]。
  5. 如果alreadyResolved.[[Value]]为true,则返回undefined。
这里有人认为尝试解决或解决已经解决或已解决的Promise应该是一个错误。由于这没有包括在ES2015规范中,因此可能永远不会添加,因为它不会与现有代码兼容。

嗨@T.J. Crowder,非常好+1,我们可以说所有的承诺都被解决了,但是并不是所有的承诺都被解决了(也许是因为它们被解决的承诺从未被解决),对吧? - user19481364
1
@Coder23 - 你说得对,不是所有的 Promise 都被解决了。但也不是所有的 Promise 都被解决了。例如:new Promise(() => {})。这将创建一个永远不会被解决或解决的 Promise。它的命运与任何其他 Promise 无关,因此它没有被解决,它永远不会被满足或拒绝,因此它永远不会解决。它将保持挂起状态,直到被垃圾回收。 :-) - T.J. Crowder
感谢 @T.J. Crowder +1,那么,使用构造函数(new Promise(...))创建的 Promise 总是未解决的,对吗? - user19481364
1
@Coder23 - 从构造函数中接收到的 Promise 可以处于任何状态或命运——未决和未解决、未决但已解决、已完成、已拒绝——这取决于您传递给 Promise 的执行器函数所做的操作。该函数是同步调用的(其目的是启动 Promise 将报告的异步操作),因此如果它同步调用 resolvereject(非典型但可能),或者它抛出错误,那么在调用构造函数的代码接收到 Promise 之前,这会影响 Promise 的状态或命运。当然,该代码无法判断,也不应关心。 :-) - T.J. Crowder
1
现在我对它有了更好的理解,谢谢 @T.J. Crowder +1 - user19481364

7
根据ECMAScript 2015 Language Spec, Promise对象
Promise是一个对象,用作延迟(可能是异步)计算的最终结果的占位符。
任何Promise对象都处于三种互斥状态之一:已完成、已拒绝和待定: 如果p.then(f, r)将立即排队调用函数f,则承诺p将被履行。 如果p.then(f, r)将立即排队调用函数r,则承诺p将被拒绝。 如果既不满足也不拒绝,则该承诺处于待定状态。 如果未处于待定状态,则承诺称为已解决,即已完成或已拒绝。 如果已解决或已“锁定”以匹配另一个承诺的状态,则该承诺已解析。 尝试解析或拒绝已解析的承诺没有效果。 如果未解决,则承诺始终处于待定状态。 已解析的承诺可以是待定的、已完成的或已拒绝的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接