【发布时间】:2018-11-05 15:22:44
【问题描述】:
我的代码:
async function run(){
process.nextTick(()=>{
console.log(1);
});
await (new Promise(resolve=>resolve()).then(()=>{console.log(2)}));
console.log(3);
process.nextTick(()=>{
console.log(4);
});
new Promise(resolve=>resolve()).then(()=>{console.log(5)});
}
run();
我的预期输出是按顺序打印 1、2、3、4、5 的数字,但我得到的是:
1
2
3
5
4
正如预期的那样,第一个nextTick 在第一个.then 回调之前被评估,因为process.nextTick 和.then 都被推迟到未来的报价,并且process.nextTick 在.then 之前声明。所以1和2按预期顺序输出。
在解决.then 之前,代码不应达到await 之后的内容,并且这可以按预期工作,因为3 会在预期的位置输出。
然后基本上我们重复了代码的第一部分,但这次.then 在process.nextTick 之前被调用。
这似乎是不一致的行为。为什么process.nextTick 在第一次回调之前调用.then 而不是第二次?
【问题讨论】:
-
我不确定,但我怀疑这与作为所谓的微任务执行的承诺回调有关。 This youtube video 很好地展示了这个概念。
-
我没有得到完整的答案,也没有兴趣详细解释事件循环中发生的事情,但那是因为第一个
nextTick是同步安排的,而第二个不是。此行为特定于本机承诺。任何非本地承诺实现都没有机会在nextTick之前安排then。async同步执行,直到第一次出现await,如果在第一次出现nextTick之前有await,情况会有所不同。 -
正如我评论你这个问题的早期版本,node.js 事件循环非常复杂。它有多种类型的事件,它以特定的顺序提供服务。但是,它下一步处理的内容更加复杂,这也取决于它在事件循环优先级的循环中的位置。不做大量工作就很难理解或预测——我个人研究了很长时间,也没有完全弄清楚。
-
我早就得出结论,您通常应该将所有异步操作视为相对于彼此随机排序,因此如果您需要特定顺序,那么您应该编写代码来强制执行命令。使一件事依赖于它之前必须发生的事情,这样无论事件循环做什么,你的代码仍然按照你需要的顺序处理事情。
-
所以,我的解释是因为在事件循环中每个
process.nextTick()被调用的位置,这导致了相对于其他类型事件的不同处理顺序。第一个process.nextTick()在事件循环位于位置A 时被调用。第二个process.nextTick()在处理了.then()回调之后被调用,这是事件循环循环的不同部分,这意味着随着事件循环的继续处理不同类型的事件,它将在第二次以不同的顺序点击process.nextTick()。
标签: javascript node.js promise async-await es6-promise