在 Promise

问题描述

代码片段:

console.log('out1');
setTimeout(() => console.log('out2'),0);
Promise.resolve('out3').then(console.log);
console.log('out4');

执行后我得到以下内容

"out1"
"out4"
"out3"
"out2"

根据我的理解,由于第 2 行和第 3 行都是异步的,所以应该先打印 out2,因为它首先被放入队列。 但这里似乎相反。

"out1"
"out4"
"out2"
"out3"
  1. 谁能解释一下我在这里遗漏了什么。
  2. 代码中的第 3 行如何仅通过传递一个 console.log 来工作

JSBin 链接https://jsbin.com/fafipezine/edit?js,console

解决方法

您可以通过在 setTimeout 函数中解析 promise 来实现此目的:

console.log('out1');

new Promise((res) => {
  setTimeout(() => {
    console.log('out2');
    res("out3");
  },0);
}).then(console.log);

console.log('out4');

您可以在 Javascript 中阅读有关这些行为的 EventLoop。

,

要回答您的问题,我们需要阐明 javascript 如何执行代码。 Javascript 跟随 run to completion model,这几乎意味着您的代码无论如何都会到达 out4 控制台日志(如果您在代码中使用 async await 或发生同步错误等,则例外) Javascript使用单线程模型,那么它是如何处理代码执行的呢? 关注你的第一个问题,我们需要看看任务队列和微任务队列是如何运作的。 这些队列基本上是为事件循环提供要做的事情。那么,它们以什么顺序被消耗?事件循环通过首先执行当前任务来消耗消息,然后继续执行可能引入的所有微任务等等(check the tasks vs microtasks topic)。 那么,什么是任务,什么是微任务? 每次请求运行代码、调用 setTimeout 或 setInterval 或触发事件(例如用户输入事件)时都会创建一个 task microtask 与任务非常相似,但它们的创建方式不同。 Promises are basically using microtasks

要回答问题的第一部分,有两个任务。第一个任务是运行这个脚本。排队的第二个任务是触发 setTimeout 的回调。在这两个任务之间,有两个 Promise(微任务)排队。以上所有结果都与您看到的打印顺序有关。 this 博文中对上述内容进行了很好的可视化,我强烈建议您阅读。

根据您的第二个问题,then function 可以使用函数引用作为参数