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

浏览器的事件循环 #77

Open
lovelmh13 opened this issue Jun 16, 2021 · 0 comments
Open

浏览器的事件循环 #77

lovelmh13 opened this issue Jun 16, 2021 · 0 comments

Comments

@lovelmh13
Copy link
Owner

lovelmh13 commented Jun 16, 2021

浏览器的事件循环

什么是事件循环

通过事件循环来不断的执行代码。统一调度任务

为什么要有事件循环

JavaScript 是单线程的。意味着每一个任务进来,就会排在下一个任务的后面,直到前面的任务执行完成以后才会执行这个任务。

img

如何在单线程上添加新的任务,就需要通过事件循环来添加了。不断的循环,如果有新的任务,就被添加到任务队列中来。

不过,这样的模式只限于当前这一个主线程上的新任务添加。

img

处理其他线程发来的任务

当有其他线程的任务想加入到主线程的时候,需要使用「消息队列」来处理。
image

IO 线程有新任务进来,添加到 消息队列 的尾部,主线程在循环的时候,从 消息队列 的头部取出任务,加入到主线程去执行。

多个线程都是操作同一个 消息队列,所以需要有一个同步锁。

消息队列里有很多种任务

如输入事件(鼠标滚动、点击、移动)、微任务、文件读写、WebSocket、JavaScript 定时器等等。可以参考Chromium 的官方源码

除此之外,消息队列中还包含了很多与页面相关的事件,如 JavaScript 执行、解析 DOM、样式计算、布局计算、CSS 动画等。

处理高优先级的任务

当使用 JavaScript 做一个发布订阅来订阅这些事件(同步),如果非常频繁的话,会使得效率变得低效。比如 DOM 的变化,DOM 经常变化,如果每次变化都通知,那么想想就很低效。

如果使用把他们变成异步的,又会失去时效性。DOM 的变化要求实时性很高。

所以,处理高优先级的任务,我们需要两个指标:高效实时

宏任务与微任务

消息队列的任务我们称为宏任务,每个宏任务里又有微任务队列。 每次宏任务执行分完成以后,会清空这个宏任务中的微任务队列。

例如,当宏任务执行的时候,DOM 有变化,那么就会把这个任务添加到当前这个宏任务的微任务队列中来。由于不会影响当前宏任务的执行,保证了高效。

等待当前这个宏任务执行完成以后,就去微任务队列里把 DOM 变化的事件解决掉。保证了实时性。

宏任务:由宿主发起的任务。

微任务:由 JavaScript 引擎发起的任务。

img

由图可以看出,全局上下文里也是有一个微任务队列的。每一个宏任务里,都会有一个微任务队列。当微任务执行的时候,如果有出现了微任务,那么还会添加到当前的微任务队列中来的,不会添加到下一个宏任务的微任务队列中去,所以会优先于下一个宏任务执行。

解决事件循环中的单个任务执行时间久的问题

JavaScript 可以通过回调功能来规避这种问题,也就是让要执行的 JavaScript 任务滞后执行。

总结

  1. 如果有一些确定好的任务,可以使用一个单线程来按照顺序处理这些任务,这是第一版线程模型。

  2. 要在线程执行过程中接收并处理新的任务,就需要引入循环语句和事件系统,这是第二版线程模型。

  3. 如果要接收其他线程发送过来的任务,就需要引入消息队列,这是第三版线程模型。

  4. 如果其他进程想要发送任务给页面主线程,那么先通过 IPC 把任务发送给渲染进程的 IO 线程,IO 线程再把任务发送给页面主线程。

  5. 消息队列机制并不是太灵活,为了适应效率和实时性,引入了微任务。

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

No branches or pull requests

1 participant