返回

超越“嚼一嚼”,深入理解JavaScript的事件循环

前端

嚼一嚼 JavaScript事件循环

JavaScript作为一门单线程语言,如何在纷繁的任务中游刃有余地执行?答案就在于它的异步编程机制和事件循环。本文将带您从理论与实战两方面深入理解JavaScript的事件循环。

一、归类请看示例代码:

console.log('你好,世界!');
setTimeout(() => {
  console.log('这是一个异步任务!');
}, 0);
console.log('再见,世界!');

执行结果:

你好,世界!
再见,世界!
这是一个异步任务!

从这个例子中,我们可以观察到以下现象:

  1. JavaScript是单线程的,因此它一次只能执行一个任务。
  2. setTimeout()函数是异步的,这意味着它不会阻塞主线程的执行。
  3. 当主线程执行完毕后,它会检查消息队列,如果发现有任务,则将它们放入执行栈执行。

二、有微则微,无微则宏

在JavaScript中,任务分为两种类型:微任务和宏任务。微任务是优先级较高的任务,而宏任务是优先级较低的任务。

微任务的例子包括:

  • Promise.then()
  • MutationObserver
  • process.nextTick()

宏任务的例子包括:

  • setTimeout()
  • setInterval()
  • I/O操作

三、总结+实战再此留下一道没有答案的题供练手

JavaScript的事件循环是一个复杂的概念,但它也是一个非常重要的概念。理解事件循环可以帮助我们更好地理解JavaScript的异步编程机制,并写出更健壮的代码。

现在,让我们一起来实战一下。请尝试回答以下问题:

在以下代码中,输出结果是什么?

console.log('你好,世界!');
setTimeout(() => {
  console.log('这是一个异步任务!');
}, 0);
Promise.resolve().then(() => {
  console.log('这是一个Promise任务!');
});
console.log('再见,世界!');

答案是:

你好,世界!
再见,世界!
这是一个Promise任务!
这是一个异步任务!

为什么Promise任务会先于setTimeout任务执行呢?这是因为Promise任务是微任务,而setTimeout任务是宏任务。微任务的优先级高于宏任务,因此它会先于宏任务执行。

参考文章