JS核心原理(1)---事件的运行机制

328 阅读2分钟

对JS稍微了解一点的,应该的都知道事件机制。
更了解一点的,可能还知道事件分为宏任务和微任务。 但是事件如何而来?任务从何而来?又如何调配呢?

为什么有事件

这是个基础问题,应该大家都知道。
但是,事件机制其实是浏览器提供的,并不是JS提供的。
这里要说明一下,JS和浏览器的关系。

1.浏览器是多进程的.浏览器渲染一个网页,一般要开启一个主进程,一个渲染进程,一个网络进程,插件进程等。
2. JS是脚本语言,需要被解释执行。JS解析引擎,比如V8,是运行在渲染进程中的。
3. JS产生任务,浏览器在主线程中进行任务循环和执行。

宏事件和微事件是怎么添加的

宏任务的类型很多,定时器,网络,onload事件,鼠标事件等。
微任务常见的只有两个,Promise.then和DOM的变化。 这里重点说一下Promise.then

const test =new Promise(res,reject=>{
    console.log("start")
    res()
})
test.then(res=>{console.log("then")})

以上的代码中,

console.log("start") 是同步的,而console.log("then")才会被作为微任务添加到事件队列中。

微任务和宏任务是添加在不同的事件队列中的。

任务是如何调度的

微任务和宏任务是怎么分配优先级的? 任务执行有两个大原则

  1. 一次性只执行一个任务
  2. 一个任务在执行的时候,是不能被打断的。不管是微任务还是宏任务。

我们看一个《JS忍者秘籍》中给的图

从图中看,顺序如下:
1.事件循环先从宏任务队列中取出一个事件
2.宏任务执行完毕之后,去微任务队列中取出事件
3. 注意,此时不是只执行一个微任务,而是会把微任务列表中所有的任务都执行完毕。
4. 微任务队列被清空之后,进行渲染。
5. 渲染更新后,回进行下一次循环。

事件与浏览器渲染

浏览器的页面刷新一般是16ms刷新一次,微任务要求在渲染之前全部执行完毕。
我们还是参考上图。
假如页面已完成了一次刷新,那么下一次16ms毫秒就会进行第二次刷新。
浏览器执行完微任务,只用了12ms,那么就会进行下一次循环,而不会直接渲染。 如果16ms时,微任务还未完成,那么回等待微任务完成才刷新。