【问题标题】:What is the reason to allow multiple resolve/reject in ES6 Promise在 ES6 Promise 中允许多次解析/拒绝的原因是什么
【发布时间】:2016-03-29 21:15:31
【问题描述】:

我发现可以(在 ES6 承诺中,在创建 Promise 对象时)使用多个解析/拒绝,这只会影响 PromiseStatus 一次,但不会影响执行流程。

var p = new Promise(function(resolve, reject) { 
    setTimeout(function(){
        resolve(1);
        console.log('Resolve 1');
    }, 50);
    setTimeout(function(){
        resolve(2);
        console.log('Resolve 2');
    }, 100);
});

setTimeout(function(){
        console.log('Status #1:', p);
    }, 10);
setTimeout(function(){
        console.log('Status #2:', p);
    }, 60);
setTimeout(function(){
        console.log('Status #3:', p);
    }, 110);

p.then(function(x){
    console.log('Value after:', x)
})

then() 函数中首先解析/拒绝将影响执行流程。 所以我的问题是 - 为什么它会这样工作(功能/错误)?

附:我的环境是 Node 4.1

附言我的输出:

Status #1: Promise { <pending> }
Resolve 1
Value after: 1
Status #2: Promise { 1 }
Resolve 2
Status #3: Promise { 1 }

【问题讨论】:

  • 不是功能,不是错误,Promise/A+ 的规范中没有任何内容表明后续尝试解决或拒绝是错误的,只是一旦实现/拒绝,承诺仍然存在以不可变的价值/原因实现/拒绝
  • 根据您的代码示例,您看到的控制台输出是什么?
  • 我认为您误解了 Promise 的关键原则 - then 回调仅在 Promise 被解决(履行或拒绝)时触发一次。而这里就是这样,你可以在控制台中轻松查看;即使执行了resolve(2) 行,也不会调用相应的then 参数函数。
  • did not allow to execute after resolve - 这听起来不可能 - 甚至无法看到它是如何用 javascript 编写的
  • 嗯,这不是 Promise 的工作方式或可以工作的方式。它们都是普通的 Javascript 函数,函数执行不能被外部杀死。 Promise 所做的只是允许您同步执行两个相关的异步代码(让then 等待,直到另一段代码发出信号)。不多也不少。并不意味着信号员已经或应该被杀死。

标签: javascript promise ecmascript-6 es6-promise


【解决方案1】:

根据 ECMAScript 2015 规范,Promise Reject FunctionsPromise Resolve Functions 部分这样说,

  1. 如果 alreadyResolved.[[value]] 为 true,则返回 undefined

所以,如果当前的 Promise 对象已经被解析,那么既不解析也不拒绝对 Promise 对象做任何事情。这实际上意味着,只有第一个解决/拒绝问题。

【讨论】:

    【解决方案2】:

    好吧,我想谈谈为什么。 Promise 是单个值的代理,因此第二次运行处理程序或更改值没有意义。例如,您不能将数字 5 更改为数字 3。

    让我们谈谈resolve 被第二次调用的替代方法。假设我们不想允许它 - 我们将如何发出信号?

    通常情况下,我们会 throw - 问题是 - 它会被捕获无处,因为 promise 构造函数中的 throws 被转换为拒绝。 .catch 处理程序不会运行,因为承诺已经解决。

    所以我们不能真正抛出,因为那意味着您无法处理的异常(这是一个非常糟糕的地方)。我们不能两次运行处理程序(这会破坏模型)。所以我们唯一的选择就是允许它。

    【讨论】:

    • 但是为什么我们不能用一个新的值第二次解决同一个承诺呢?只有第一个决心生效的原因是什么?如果允许多个解析,那么我们可以拥有流数据之类的东西!
    • @FaizHalde 一个函数只能返回一个值(它完成了一个返回)。如果您想使用流式 API,请查看异步迭代器(第 3 阶段)或可观察对象(第 1 阶段)
    • @FaizHalde 您应该检查与 Promise 有点相似但可以随着时间推移发出多个值的观察者。我最近才遇到它,我自己正在经历它。
    猜你喜欢
    • 1970-01-01
    • 2014-09-03
    • 1970-01-01
    • 2011-01-20
    • 1970-01-01
    • 2021-06-26
    • 2011-09-09
    • 2015-09-28
    • 1970-01-01
    相关资源
    最近更新 更多