承诺输出因NodeJ和浏览器而异

时间:2015-07-31 22:55:39

标签: javascript node.js google-chrome promise

以下代码块在Node和浏览器之间执行不同的操作。当然,存在不同的环境,不同的处理时间和竞争条件的可能性。但根据我对Promises的理解,这段代码应该在环境之间保持一致。

我希望Chrome /浏览器的结果。我不指望NodeJs的结果。我不明白为什么每个newPromise的{​​{1}}链未在 then的{​​{1}}链继续之前完成。换句话说,因为新的Promise被返回到当时masterPromise中的then promise链,我希望新的Promise的then-chain能够在masterPromise promise-chain恢复之前完成。 / p>

我很乐意,如果有人可以在下面的实现中找到一个漏洞,并解释为什么NodeJs结果是有效的!

使用chrome 44和节点12.6。

例如:

masterPromise

节点:

fn

铬:

'use strict';
var masterPromise = Promise.resolve();
var numbers = [ 1, 2, 3 ];

// function returns a new promise that fulfills in 100ms
// it logs two bits of information--one pre-resolve, & one post-resolve.
// because a `.then` is registered immediately, before the promised is
// fulfilled, i would expect the post-resolve console.log to be logged before
// any other logging
var returnNewPromise = function(number) {
    var resolve;
    var newPromise = new Promise(function(r) { resolve = r; });
    newPromise.then(function() { console.log('registered ' + number + ' (verbatim, syncronous echo)'); });
    setTimeout(function() {
        console.log('registered ' + number);
        resolve();
    }, 100);
    return newPromise;
};

numbers.forEach(function(number) {
    var getChildPromise = function(number) {
        return returnNewPromise(number);
    };
    return masterPromise.then(function() {
        return getChildPromise(number);
    });
});

2 个答案:

答案 0 :(得分:2)

  

我不明白为什么每个newPromise then chain都不会立即执行其解析

然后 - 回调不会立即调用。

var resolve;
new Promise(function (r) { resolve = r; })
    .then(function () { console.log(2); });
resolve();
console.log(1);

日志:

1
2

Promise resolving的行为类似于setTimeout,没有延迟。

<强>更新

setTimeout的比较并不完全正确,因为有限制: https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout#Minimummaximum_delay_and_timeout_nesting 相似之处在于异步的承诺。

<强> UPDATE2:

-----------+------------
wait       |  resolved
-----------+------------
timeout1   |             initial state
timeout2   |
-----------+------------
           | timeout1    after 100 ms
timeout2   |
-----------+------------
           | resolve1    then Chrome variant
           | timeout2
-----------+------------
           | timeout2    or Node variant
           | resolve1
-----------+------------

两种变体均符合规范。 Chrome队列似乎在后续超时回调之前解决了回调问题。

答案 1 :(得分:2)

  

我不明白为什么每个newPromise的{​​{1}}链都没有   之前完成 then的{​​{1}}链继续。一个新的   承诺在当时返回到masterPromise承诺链   then,所以不应该在masterPromise之前等待   承诺链简历?

没有。你的误解似乎是关于“masterPromise chain”:没有这样的事情 您有一个masterPromise,然后您已经链接了三个不同的fn来电。当masterPromise结算(立即)时,它会看到3个回调,并按照注册顺序调用所有这些回调。 不关心这些回调是做什么的,无论它们是否是异步的,并且不等待它们的承诺结果。在你的情况下,所有这些都创造了承诺,并通过它们推进了他们的子链,但这3个子链完全相互独立。

使用更具描述性的日志记录来充实你的代码有助于理解你在做什么:

then

您将在此处看到的日志是

masterPromise

在这里,我们可以看到3个(独立的)function delay(number) { console.log("creating promise for", number); return new Promise(function(resolve) { setTimeout(function() { console.log('resolving promise with', number); resolve(number); }, 100); }); }; function result(n) { console.log("received", number); } var masterPromise = Promise.resolve(); masterPromise.then(function(){ delay(1).then(result); }); // chain 1 masterPromise.then(function(){ delay(2).then(result); }); // chain 2 masterPromise.then(function(){ delay(3).then(result); }); // chain 3 console.log("created chains"); 来电。他们将尽快安排各自的回调(// .then chain 1 -------, // .then chain 2 ------- \ -, // .then chain 3 -------- \ -\ -, created chains | | | | | | 3 then callbacks in the order they were registered creating promise for 1 <´ | | // setTimeout 100 -----, | | \ / | creating promise for 2 | <-´ | // setTimeout 100 ------ |-, / | \ / creating promise for 3 | | <-´ // setTimeout 100 ------ |- |-, | | \ … | | | 3 timeout callbacks in the order they were scheduled | | | resolving promise with 1 <´ | | // resolve() | | […] / | resolving promise with 2 <-´ | // resolve() / […] / resolving promise with 3 <---´ // resolve() […] 。这里是节点和Chrome之间的区别:前者确实在同一时间点执行超时回调(它们是在相同的超时时间内同时安排),而Chrome使用单独的刻度。所以在节点中,“asap”是在三个回调之后,而在Chrome中它位于它们之间。两种实现都很好。