js事件循环机制

1. JavaScript 的执行环境

  • 单线程:JavaScript 是单线程的,这意味着它在同一时间只能执行一个任务。这种设计使得 JavaScript 在处理并发操作时需要依赖事件循环。

2. 执行栈(Call Stack)

  • 定义:执行栈是一个后进先出(LIFO)的数据结构,用于管理函数调用。每当一个函数被调用时,它会被推入栈中;当函数执行完毕后,它会被弹出栈外。

3. Web APIs

  • 定义:Web APIs 是浏览器提供的异步操作接口,用于处理如网络请求、定时器、DOM 事件等操作。
  • 工作原理:当 JavaScript 代码执行时,如果遇到异步操作,这些操作会被发送到 Web APIs 进行处理。处理完成后,Web APIs 会将相应的回调函数放入消息队列。

4. 消息队列(Callback Queue)

  • 定义:消息队列是一个先入先出(FIFO)的数据结构,用于存储待处理的回调函数。只有当执行栈为空时,事件循环才会从消息队列中取出一个回调函数并执行。

5. 微任务队列(Microtask Queue)

  • 定义:微任务队列用于存储微任务(如 Promise 的 thencatchfinally 回调和 MutationObserver)。
  • 优先级:微任务的执行优先级高于宏任务。在处理消息队列中的宏任务之前,事件循环会先执行所有的微任务。

6. 事件循环(Event Loop)

事件循环的主要工作流程如下:

  1. 检查执行栈:事件循环首先检查执行栈是否为空。
  2. 处理微任务:
    • 如果执行栈为空,事件循环会先处理微任务队列中的所有微任务。
  3. 处理宏任务:
    • 处理完所有微任务后,事件循环会从消息队列中取出一个宏任务并将其推入执行栈中。
  4. 重复过程:重复步骤 1 至 3,直到消息队列和微任务队列都为空。

7. 任务的优先级

  • 微任务:如 Promise 的回调,具有高优先级,优先于宏任务执行。
  • 宏任务:如 setTimeoutsetInterval、I/O 操作等。

事件循环的工作示例

 

 
javascript
console.log('A'); // 1

setTimeout(() => {
    console.log('B'); // 5
}, 0);

Promise.resolve().then(() => {
    console.log('C'); // 3
    setTimeout(() => {
        console.log('D'); // 7
    }, 0);
});

setTimeout(() => {
    console.log('E'); // 6
}, 0);

Promise.resolve().then(() => {
    console.log('F'); // 4
});

console.log('G'); // 2
posted @ 2024-10-29 10:40  植物的空白  阅读(147)  评论(0)    收藏  举报