有关 Javascript 中微任务队列检查点的详细信息

问题描述 投票:0回答:1

基于这个关于JS中微任务队列检查点的公认答案并更多地查找这个概念,我开始理解以下内容:

微任务队列检查点发生在事件循环中的这些点:

  • 脚本执行后:当 JavaScript 调用堆栈完成处理时,事件循环将首先运行任何挂起的微任务,然后再处理其他任何事情。
  • 每个宏任务之后:每当任务队列中的任务(例如,单击的事件处理程序)完成时,就会出现另一个微任务检查点,在移动到下一个宏任务之前再次处理任何微任务。

为了通过示例理解这一点,我尝试了以下代码示例:

setTimeout(() => {
    console.log('timeout1');
}, 3000);

setTimeout(() => {
    console.log('timeout2');
}, 3000);

let promise = new Promise(function (resolve, reject) {
    setTimeout(() => resolve('promise!'), 3000);
});

promise.then(
    (result) => console.log(result),
    (err) => console.log(err)
);

根据JS中事件循环的概念,setTimeouts函数会在指定的时间过去后被推送到宏任务队列中。因此,所有三个 setTimeout 任务都应该在 3 秒过去后被推送到宏任务队列中。另一方面,传递给 Promise 的 .then() 的函数应该被推送到微任务队列。对于上面的代码,在后续循环开始时,应该运行第一个被推送到宏任务队列的 setTimeout 任务来打印“timeout1”。

根据我上面提供的微任务队列检查点概念,此后应该会出现检查点,并且微任务队列中的打印函数应该打印“promise!”。

最后,应打印宏任务队列“timeout2”上的第二个宏任务。

但是,在 Chrome 和 Firefox(最新版本)的控制台上,并通过我的机器上的 Node v16.14.0 运行代码,我发现打印的顺序是:

timeout1
timeout2
promise!

微任务队列检查点行为是否无法保证?如果是的话,我的评估是否在其他地方出错了?

javascript asynchronous promise settimeout event-loop
1个回答
0
投票

将记录

"promise!"
的微任务将在从 Promise 构造函数调度的计时器任务执行后立即执行,但其他两个计时器任务是在该任务之前调度的,因此它们首先执行。事实上,从 Promise 的决议中排队的微任务在这里并不重要:

setTimeout(() => {
    console.log('timeout1');
}, 3000);

setTimeout(() => {
    console.log('timeout2');
}, 3000);

let promise = new Promise(function (resolve, reject) {
    setTimeout(() => {
      resolve('promise!');
      // 'timeout3' will be logged before 'promise!' but after both other timeouts
      // because these got queued before us.
      console.log('timeout3'); 
    }, 3000);

});

promise.then(
    (result) => console.log(result),
    (err) => console.log(err)
);

© www.soinside.com 2019 - 2024. All rights reserved.