事件循环(eventloop)

156 阅读2分钟

讲解可看: 【事件循环】【前端】事件原理讲解 image.png
主线程会执行任务队列中的任务,并在固定的时间内(如每秒60次)进行渲染

button.addEventListener('click',()=>{
    box.style.display ='none';
    box.style.display = 'block';
    box.style.display = 'none';
    box.style.display = 'block';
    box.style.display = 'none';
    box.style.display = 'block';
    box.style.display = 'none';
});

并不会出现反复显示隐藏的效果,只会渲染最后一次

什么是事件循环

  1. JS是单线程,防止代码阻塞,我们把代码(任务)分为:同步和异步
  2. 同步代码给js引擎执行,异步代码交给宿主环境(浏览器、Node)
  3. 同步代码放入执行栈中,异步代码等待时机成熟送入任务队列排队
  4. 执行栈执行完毕,会去任务队列看是否有异步任务,有就送到执行栈执行,反复循环查看执行,这个过程是事件循环(eventloop)

原理

执行顺序:同步=》事件循环=》微任务=》宏任务
其核心原理如下:

  1. 执行栈(Call Stack)
    同步任务直接进入执行栈,按顺序执行。遇到异步任务时,JavaScript 会将其回调函数注册到对应的任务队列中,继续执行后续代码

  2. 任务队列(Task Queue) 异步任务完成后,回调函数会被放入任务队列。任务队列分为两种:

    • 宏任务队列(Macrotask Queue) :包含 ScriptsetTimeoutsetInterval、I/O 操作、DOM 事件等 

    • 微任务队列(Microtask Queue) :包含 Promise.thenMutationObserverprocess.nextTick(Node.js)等 

  3. 事件循环流程

  • 执行同步代码:所有同步任务(视为第一个宏任务)在主线程依次执行。

  • 处理微任务队列:检查微任务队列,依次执行所有微任务,直到队列清空(包括执行过程中新添加的微任务)。

  • 执行下一个宏任务:从宏任务队列中取出一个任务执行。

  • 重复步骤 2-3:形成事件循环,直至所有任务完成。

  • 示例

    console.log('Start');
    setTimeout(() => console.log('宏任务'), 0);
    Promise.resolve().then(() => console.log('微任务'));
    console.log('End');
    // 输出顺序:Start → End → 微任务 → 宏任务
    

image.png
点击后输出为:Listener 1→MicroTask 1→Listener 2→MicroTask 2

image.png
点击后输出为:Listener 1→Listener 2→MicroTask 1→MicroTask 2