上次听我的一个前端朋友谈到自己面试时出了一道题:一次事件渲染流程和渲染时机听到这个问题的时候——我:?????
后面查了一下相关的知识,现在对这个问题稍微做一下整理,如果有说的不对的地方希望大家多多指正。
事件循环机制(Event Loop)
讲到事件循环机制就需要去了解一下单线程与多线程的概念了。这方面的知识在这就麻烦读者自己去了解了,这里我们只需要知道JS是单线程的。也就是说JS在同一时刻只会去做一件事情。但是我们平时在工作中编写前端代码的时候经常会对自己的代码进行事件调用、异步请求、调用接口(API)等,这时候事件循环机制就开始工作了。主要的就是以下几步:
1)执行一个宏任务,一般第一个宏任务为整个JavaScript代码块(执行栈中没有就从事件队列中获取);
2)执行过程中如果遇到微任务,就将它添加到微任务的任务队列中;
3)宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行),而在执行期间产生的微任务会被放到微任务队列的末尾等待被执行;
4)当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
5)渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取),如果宏任务队列为空,休眠一直到下一个宏任务出现。
宏任务
产生宏任务的主要来源有:
- DOM操作
- 监听事件回调(键盘、鼠标事件等)
- AJAX请求
- 调用浏览器API(如:history.back() )
- setTimeout / setInterval
- 操作IndexDB
以上产生的事件,每次只会执行一件,即JS单线程原理。
微任务
产生微任务的主要来源有:
- Promise的.then()、.catch()、.finally();
- MutationObserver
- Object.observe
微任务队列中的事件会按照顺序逐步执行。