Shane Jix

JavaScript Event Loop in Browser

create:January 14, 2022  update:April 12, 2022  ☕️ 3 min read

同步链接: https://www.shanejix.com/posts/JavaScript Event Loop in Browser/

浏览器(多进程)其实就是是一个异步非阻塞模型的实现,当新建一个Tab 页面时,就会新开一个进程。一个 Tab 页面从加载到渲染需要在浏览器内核(多线程)的调度下控制各线程互相配合以保持同步。浏览器常驻线程包括:GUI 渲染线程,JavaScript 引擎线程,定时触发器线程,事件触发线程,异步 http 请求线程等。

虽然 JavaScript 引擎线程时单线程,但是浏览器时内核是多线程,EventLoop 正是浏览器异步非阻塞模型实现的关键,线程通信的桥梁。

循环阶段:

   ┌───────────────────────┐
┌─>│        script         │
│  └──────────┬────────────┘
│             │
│         microtasts
│             │
│           render
│             │
│  ┌──────────┴────────────┐
│  │      mousemove        │
│  └──────────┬────────────┘
│             │
│         microtasts
│             │
│           render
│             │
│  ┌──────────┴────────────┐
└──│      setTimeout       │
   └───────────────────────┘

简化版事件循环算法:

1. 从 宏任务 队列(例如 “script”)中出队(dequeue)并执行最早的任务

2. 执行所有 微任务:

   - 当微任务队列非空时:

   - 出队(dequeue)并执行最早的微任务

3. 如果有变更,则将变更渲染(render)出来

4. 如果宏任务队列为空,则休眠直到出现宏任务

5. 转到步骤 1

详细算法流程参见规范:event-loop-processing-model 动态观察 JS Stack ,Tasks Queue, MicoTasks Queue的详细变化参见:tasks-microtasks

注意点:

- 微任务会在上一次宏任务中入队或者在执行微任务队列时入队

- 微任务会在执行 [任何其他事件处理,或渲染,或执行任何其他] 宏任务 之前完成(确保了微任务之间的应用程序环境基本相同如没有鼠标坐标更改,没有新的网络数据等)

宏任务(macrotask,也叫 task),由宿主(浏览器、Node)发起。如下类型异步任务的回调会进入 MacroTask Queue:

  • script(整体代码)
  • setTimeout
  • setInterval
  • setImmediate (Node 独有)
  • requestAnimationFrame (浏览器独有)
  • I/O
  • 事件队列
  • UI rendering (浏览器独有)

微任务(microtask,也叫 jobs),由 JS 自身发起。 如下类型异步任务的回调会进入 MicroTask Queue:

  • process.nextTick (Node 独有)
  • Promise
  • async/await(实际就是 promise)
  • Object.observe
  • MutationObserver(html5 新特性)

总结

一句话概述什么是事件循环:

在每个宏任务执行末尾,会插入微任务队列(微任务产生于当次宏任务或微任务),然后 pop 出宏任务队列继续执行

EventLoop 不仅仅是靠的 JS 执行线程的单独工作,其背后是浏览器多线程的相互协作和通信

references

作者:shanejix 出处:https://www.shanejix.com/posts/JavaScript Event Loop in Browser/ 版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。 声明:转载请注明出处!

Edit on GitHubDiscuss on GitHub


Shane Jix

Personal blog by Shane Jix. I explain with words and code.

LinksTools
© 2019 - 2022, Built withGatsby