EventLoop - 事件循环

发布于: 5/2/2022 阅读大约需要1分钟

JS是单线程的(避免多个线程同时操作DOM造成的困扰),非阻塞的(eventloop)
既然JS是单线程的,那就意味着JS中执行的任务需要排队, 也就产生了 任务队列
而任务又分为两种: 同步任务异步任务
所有同步任务都在主线程上执行, 形成一个执行栈(stack)
异步任务将会被放到 任务队列(先进先出)

Untitled.png

MacroTasks - 宏任务

我们常见的以下任务都属于宏任务

  • script(整体代码)
  • 定时器(setTimeout, setInterval)
  • I/O
  • UI交互事件
  • 浏览器渲染

MicroTasks - 微任务

每个宏任务执行完成之后都会立即执行微任务队列中的所有任务

  • Promise.then/catch/finally()
  • MutationObserver
  • queueMicrotask(fn)

测试:

const button = document.querySelector('.btn')
button.addEventListener('click', () => {
  Promise.resolve().then(() => console.log('Microtask1'))
  console.log('Listener1')
})
button.addEventListener('click', () => {
  Promise.resolve().then(() => console.log('Microtask2'))
  console.log('Listener2')
})
 // 然后点击button

上面代码的输出结果为:

 Listener1
 Microtask1
 Listener2
 Microtask2

然后, 我们使用JS来模拟用户点击事件

// same code...
 button.click() // 因为此时该语句位于 stack 中并未执行结束, 所以不会执行微任务

输出结果为:

 Listener1
 Listener2
 Microtask1
 Microtask2

参考链接