承诺输出在NodeJs和Browser之间是不同的
Promise output varies between NodeJs and Browser
以下代码块在Node和Browser之间的执行方式不同。当然,存在不同的环境、不同的处理时间和竞争条件的可能性。但是根据我对Promises的理解,这些代码应该在不同的环境中保持一致。
我期待Chrome/浏览器的结果。我不期望NodeJs的结果。我不明白为什么每个newPromise
的then
链在 masterPromise
的then
链继续之前没有完成。换句话说,因为一个新的Promise在随后的fn
中被返回到masterPromise
Promise -chain,我希望新Promise的then-chain在masterPromise Promise -chain恢复之前完成。
我希望有人能在下面的实现中戳一个洞,并解释为什么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);
});
});
节点: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)
我不明白为什么每个
newPromise
的then
链不是在之前完成,masterPromise
的then
链继续。一个新的Promise在then中返回到masterPromise
Promise -chainfn
,所以它不应该在masterPromise之前等待promise-chain简历吗?
。看来你的误解是关于"masterPromise链":没有这样的东西。
您有一个masterPromise
,然后您从它链接了三个不同的then
调用。当masterPromise
解析时(这是立即的),它看到3个回调,并按照它们注册的顺序调用它们。它不关心这些回调做什么,它们是否是异步的,也不等待它们的承诺结果。在你的例子中,它们都创建了承诺,并通过它们推进它们的子链,但这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之间的区别:前者在相同的tick中执行相同时间的超时回调(它们被安排在相同的超时时间),而Chrome使用单独的tick。所以在节点中,"asap"是在三个回调之后,而在Chrome中它是在它们之间。
我不明白为什么每个newPromise then链在解析时没有立即执行
then-回调不立即调用。
var resolve;
new Promise(function (r) { resolve = r; })
.then(function () { console.log(2); });
resolve();
console.log(1);
日志:1
2
承诺解析与setTimeout
一样,具有零延迟。
更新:
与setTimeout
的比较不太正确,因为有局限性:https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout#Minimummaximum_delay_and_timeout_nesting相似之处在于异步类型的承诺。
更新2:
-----------+------------
wait | resolved
-----------+------------
timeout1 | initial state
timeout2 |
-----------+------------
| timeout1 after 100 ms
timeout2 |
-----------+------------
| resolve1 then Chrome variant
| timeout2
-----------+------------
| timeout2 or Node variant
| resolve1
-----------+------------
两个变体都符合规范。Chrome队列似乎在随后的超时回调之前解决回调。
- 为什么_self结果是不同的价值观
- 使用 JQuery 读取二进制文件的浏览器之间的不同行为
- 同一元素的 this.id 值在浏览器之间是不同的
- angularjs+ui.router:指令控制器和链接函数之间的不同行为
- 模拟浏览器和服务器之间的不同时区以进行本地测试
- getComputedStyle报告Chrome / Safari / Firefox和IE11之间的不同高度
- Google Geocoder 在 url 和 javascript 请求之间有不同的结果
- jQuery fx速度是不同的速度
- 如何解释浏览器之间的不同“存储”事件行为
- 为什么 Number.parseInt 和全局的 parseInt 是不同的
- 什么是不同的betweet moment().utc().toISOString()和moment().utc().fo
- Javascript 日期在 Internet Explorer 和 Chrome 之间有不同的结果
- PHP 'rawurlencode' 和 JS 'encodeURIComponent' 之间的不同行为是否重要?
- 在输入和输出区域之间具有不同的行高
- React路由器中Link和Anchor标签之间的不同行为
- Highcharts-悬停时x坐标之间的不同填充颜色
- 在实际的DOM中,用javascript创建的Div结构是不同的
- 在成功部分的Ajax发布方法中,发布数据的顺序和获取数据的顺序是不同的
- 时区之间的日期转换是不同的
- 承诺输出在NodeJs和Browser之间是不同的