📜  JavaScript 事件循环中的微任务和宏任务是什么?(1)

📅  最后修改于: 2023-12-03 15:01:40.823000             🧑  作者: Mango

JavaScript 事件循环中的微任务和宏任务是什么?

JavaScript 的事件循环机制是 JavaScript 的重要部分之一,在理解 JavaScript 的异步编程方面扮演了关键角色。事件循环机制可以让某个 JavaScript 代码块异步执行而不会阻塞主线程,从而使 Web 应用程序变得更加灵活和响应。在事件循环机制中,有两种主要的任务类型:微任务和宏任务。

宏任务

宏任务就是指 JavaScript 执行栈中的任务,包括从事件循环队列中取出的任务(如在 setTimeout 中传递的函数)和用户输入事件(如点击事件)等。宏任务通常是异步执行的,因为它们被放在事件队列中并等待执行。

在执行宏任务时,JavaScript 会将一个宏任务执行完毕后才会去检查待处理的微任务队列,如果有微任务就会执行微任务。因此,在执行宏任务期间产生的微任务会在下一个事件循环中执行。下面是一个例子:

console.log("1");

setTimeout(function() {
  console.log("2");
}, 0);

console.log("3");

上述代码的输出结果将是:“1”,“3”,“2”,因为在执行完“1”和“3”之后,setTimeout 中传递的函数被放入了事件队列,等待执行。当执行完当前宏任务时,JavaScript 会检查微任务队列并执行微任务。由于我们的例子中没有微任务,因此 JavaScript 继续处理事件队列中的下一个宏任务,即 setTimeout 中传递的函数,输出“2”。

微任务

微任务在概念上和宏任务类似,但是微任务比宏任务优先级更高,在事件循环机制中的位置也更靠前,因此在 JavaScript 第一次执行完宏任务后会首先检查微任务队列,如果有微任务则执行微任务。简而言之,微任务就是在当前宏任务执行完毕后需要立即执行的任务。

常见产生微任务的场景有:

  • Promise 的 then 方法
  • async/await
  • MutationObserver.observe

下面是一个例子:

console.log("1");

setTimeout(function() {
  console.log("2");
}, 0);

Promise.resolve().then(function() {
  console.log("3");
});

console.log("4");

上述代码的输出结果将是:“1”,“4”,“3”,“2”,因为在执行完“1”和“4”之后,Promise.then 中的函数被放入微任务队列,等待执行。此时,JavaScript 检查微任务队列并执行微任务,输出“3”。由于该微任务执行完毕后并没有再次产生微任务,因此 JavaScript 继续处理事件队列中的下一个宏任务,即 setTimeout 中传递的函数,输出“2”。

微任务和宏任务的执行顺序是在任何情况下都要遵循的,这也是 JavaScript 事件循环机制中的重要一环。为了更好地遵循执行顺序,可以使用 Promise.resolve().then() 方式创建一个微任务。值得注意的是,如果在一个微任务处理期间产生了另外的微任务,则这些新的微任务会被插入到等待的微任务队列中,并在当前微任务完成后立即执行。

总结一下:

  • 宏任务是 JavaScript 执行栈中的任务
  • 微任务是宏任务之后需要立即执行的任务
  • 进入一个新的宏任务之前,JavaScript 会检查除了该宏任务之外的所有微任务
  • 微任务和宏任务有固定的执行顺序
  • 因为微任务在宏任务之前执行,因此它们可以用来实现异步代码