• 主页

  • 投资

  • IT

    🔥
  • 设计

  • 销售

  • 共299篇

    前端 - Javascript

关闭

返回栏目

关闭

返回前端 - Javascript栏目

150 - 事件循环 - 事件循环机制 - 执行栈与任务队列

作者:

贺及楼

成为作者

更新日期:2025-02-21 20:09:27

事件循环 - 事件循环机制 - 执行栈与任务队列

在前端开发的世界里,JavaScript 是一门至关重要的编程语言。而理解 JavaScript 的事件循环机制、执行栈和任务队列,就像是掌握了一把解开异步编程谜题的钥匙。接下来,让我们一起深入探索这神秘的领域。

单线程的 JavaScript

JavaScript 是单线程的,这意味着它一次只能执行一个任务。单线程的好处是避免了复杂的线程同步问题,但也带来了一个弊端:如果遇到耗时的任务,后面的代码就会被阻塞。想象一下,你在银行排队办理业务,只有一个窗口在工作,如果前面的人办理业务特别慢,后面的人就只能干等着。

  1. console.log('开始');
  2. // 模拟一个耗时任务
  3. for (let i = 0; i < 1000000000; i++) {}
  4. console.log('结束');

在上面的代码中,for 循环是一个耗时任务,在它执行的过程中,后面的 console.log('结束') 语句会被阻塞,直到 for 循环执行完毕。

执行栈

执行栈是 JavaScript 用来管理函数调用的一种数据结构,它遵循后进先出(LIFO)的原则。当我们调用一个函数时,这个函数会被压入执行栈的顶部,当函数执行完毕后,它会从执行栈中弹出。

  1. function func1() {
  2. console.log('func1 开始');
  3. func2();
  4. console.log('func1 结束');
  5. }
  6. function func2() {
  7. console.log('func2 开始');
  8. console.log('func2 结束');
  9. }
  10. func1();

执行过程如下:

  1. 调用 func1func1 被压入执行栈。
  2. func1 内部调用 func2func2 被压入执行栈。
  3. func2 执行完毕,从执行栈中弹出。
  4. func1 继续执行,执行完毕后从执行栈中弹出。

任务队列

为了解决单线程阻塞的问题,JavaScript 引入了任务队列。任务队列分为宏任务队列和微任务队列。

宏任务

常见的宏任务有 setTimeoutsetIntervalI/O 操作、UI 渲染 等。

微任务

常见的微任务有 Promise.thenMutationObserver 等。

当遇到异步任务时,JavaScript 会将其交给浏览器的其他线程去处理,当异步任务完成后,会将对应的回调函数放入任务队列中。

  1. console.log('同步任务 1');
  2. setTimeout(() => {
  3. console.log('宏任务回调');
  4. }, 0);
  5. Promise.resolve().then(() => {
  6. console.log('微任务回调');
  7. });
  8. console.log('同步任务 2');

执行顺序分析:

  1. 执行 console.log('同步任务 1'),这是一个同步任务。
  2. 遇到 setTimeout,将其回调函数放入宏任务队列。
  3. 遇到 Promise.then,将其回调函数放入微任务队列。
  4. 执行 console.log('同步任务 2')
  5. 同步任务执行完毕,检查微任务队列,执行 console.log('微任务回调')
  6. 微任务队列清空后,检查宏任务队列,执行 console.log('宏任务回调')

事件循环

事件循环是 JavaScript 实现异步编程的核心机制。它的工作流程如下:

  1. 从执行栈中执行同步任务。
  2. 当执行栈为空时,检查微任务队列,如果微任务队列不为空,依次执行微任务,直到微任务队列为空。
  3. 微任务队列清空后,从宏任务队列中取出一个宏任务放入执行栈执行。
  4. 重复步骤 2 和 3。
步骤 操作
1 执行执行栈中的同步任务
2 检查微任务队列,执行所有微任务
3 从宏任务队列中取出一个宏任务执行
4 重复步骤 2 和 3

总结

理解 JavaScript 的事件循环机制、执行栈和任务队列对于编写高效的异步代码至关重要。通过合理地利用异步任务和任务队列,我们可以避免代码阻塞,提高程序的性能。希望这篇文章能帮助你更好地掌握 JavaScript 的异步编程。

现在,你就像一个经验丰富的银行经理,能够有条不紊地安排客户办理业务,让 JavaScript 程序在单线程的情况下也能高效运行。