Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript Event Loop in Browser #90

Open
shanejix opened this issue Jan 14, 2022 · 0 comments
Open

JavaScript Event Loop in Browser #90

shanejix opened this issue Jan 14, 2022 · 0 comments

Comments

@shanejix
Copy link
Owner

shanejix commented Jan 14, 2022

同步链接: 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 国际」许可协议进行许可。
声明:转载请注明出处!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant