javascript - Promise 输出因 NodeJs 和浏览器而异

标签 javascript node.js google-chrome promise

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

我期待 Chrome/浏览器的结果。我不期望 NodeJs 结果。我不明白为什么每个 newPromisethen 链在 masterPromise 之前都没有完成 然后 链继续。换句话说,因为在 then fn 中将新的 Promise 返回到 masterPromise promise-chain,我希望新 Promise 的 then-chain 在 masterPromise 之前完成 promise 链恢复。

如果有人能在下面的实现中找出一个漏洞,并解释为什么 NodeJs 结果有效,我会很高兴!

使用 chrome 44 和 Node 12.6。

例如:

'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);
    });
});

Node :

registered 1
registered 2
registered 3
registered 1 (verbatim, syncronous echo)
registered 2 (verbatim, syncronous echo)
registered 3 (verbatim, syncronous echo)

Chrome :

registered 1
registered 1 (verbatim, syncronous echo)
registered 2
registered 2 (verbatim, syncronous echo)
registered 3
registered 3 (verbatim, syncronous echo)

最佳答案

I do not understand why each newPromise's then chain is not completed before the masterPromise's then chain continues. A new Promise is returned to the masterPromise promise-chain in a then fn, so shouldn't it wait for that before the masterPromise promise-chain resumes?

没有。看来你的误解是关于那个“masterPromise链”:没有这样的东西。
您有一个 masterPromise,然后您从中链接了三个不同的 then 调用。当 masterPromise 解析时(即刻),它会看到 3 个回调并按注册顺序调用所有回调。它不关心这些回调做什么,它们是否异步,也不等待它们的 promise 结果。在你的例子中,它们都创建了 promise ,并通过它们推进了它们的子链,但这 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()
[…]

在这里我们可以看到发生了 3 个(独立的)resolve() 调用。他们将各自安排各自的回调(result)尽快。这是 Node 和 Chrome 之间的区别:前者确实在同一时间执行超时回调(它们被安排在同一时间并具有相同的超时),而 Chrome 使用单独的时间。所以在 node 中,“asap”在三个回调之后,而在 Chrome 中,它在它们之间。两种实现都很好。

关于javascript - Promise 输出因 NodeJs 和浏览器而异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31756375/

相关文章:

javascript - 运行许多查询时,Chrome 与 Web SQL 中的问题/错误?

javascript - 循环遍历对象直到找到参数(VueJS)

node.js - 哪个 IDE 支持 Node.js 应用程序的 CoffeeScript 调试(源映射、断点和调用堆栈)?

javascript - 在 nodejs 和 express 中使用 fluent-ffmpeg 下载视频

javascript - 如何在Javascript中异步使用对象?

javascript - 尝试在 Chrome 扩展程序中使用 SignalR 连接到集线器时出错

javascript - 在 JavaScript + jQuery 网络应用程序中将 UI 与模型数据链接的最佳实践

javascript - 处理 JSON 创建一个普通数组而不是 JSON 对象

javascript - 从子类 ReactJS 将参数传递给父类中的事件处理程序

javascript - 如何更改网站 JavaScript 代码中的变量值?