Event Loop知识点

421 阅读3分钟

更多文章

前言

整理一下事件运行机制,主要是浏览器的,node没有深究过,也说不好,就不说太多关于node的了

Event Loop

  • js单线程
  • 单线程任务分为同步任务异步任务
  • 异步任务又分为宏任务(MacroTask)和微任务(MicroTask)

上边是一些知识点,接下来说一下Event Loop执行过程:

从script开始,任务按顺序进入执行栈中,同步任务在主线程中直接被执行,遇到异步任务时,异步任务会进入异步处理模块并注册相应的回调函数,注册完成后回调函数进入任务队列(遇到微任务进入微任务队列,遇到宏任务开启一个新的宏任务队列),待同步任务执行完执行栈为空时,依次进入栈中执行,每次执行宏任务之前会检查是否存在微任务,如果存在则将微任务队列中的所有任务执行完后再执行宏任务

每遇到一个宏任务会开启一个新的宏任务队列,而微任务队列只有一个,执行宏任务若发现新的微任务,会将微任务加入微任务队列,所以当开始执行一个新的宏任务时,如果微任务队列中有新的任务,先执行一遍微任务,看一个demo:

console.log(1)
setTimeout(()=>{
    console.log(2)
    Promise.resolve(3).then(res=>console.log(res))
}, 0)
setTimeout(()=>{
    console.log(4)
}, 0)
Promise.resolve(5).then(res=>console.log(res))
console.log(6)
// 执行结果: 1 6 5 2 3 4
// 1 6 5 2,正常的逻辑同步=>微任务=>宏任务
// 执行4会检查微任务队列中是否存在任务,此时会发现3,所以执行3,然后执行宏任务4

宏任务&微任务

常见宏任务:

  • script(全局任务)
  • setTimeout
  • setInterval
  • setImmediate
  • I/O
  • UI render

常见微任务:

  • Promise.then()/catch()/finally()
  • MutationObserver
  • process.nextTick(node.js)

区别:

宏任务微任务
谁发起node/浏览器js引擎
运行先后
触发新一轮Tick不会

如果面试的时候面试官问你什么是宏任务、什么是微任务,而你已经说了很多,那就把区别在讲给他好了

setTimeout&requestAnimationFrame

  • setTimeout

W3C在 HTML标准中规定,规定要求setTimeout低于 4ms的时间间隔算为 4ms

setTimeout(setInterval类似)经常用来做动画,但根据我们之前了解的Event Loop机制,实际上setTimeout并不会按照实际设置的时间执行,如下:

const startTime = new Date().getTime();
setTimeout(()=>{
  console.log(`时差:${new Date().getTime()-startTime}`); //时差:1348
},1000);
for(let i = 0;i<10000;i++){
  console.log(1)
}
// 我们设定的是1s执行,实际执行时间会超过1s

另一个问题是刷新频率受屏幕分辨率和屏幕尺寸影响,我们无法确定屏幕的刷新频率,而setTimeout又只能设定一个固定值,所以我们更新动画的时间和屏幕刷新的频率会不一致,导致丢帧的问题

  • requestAnimationFrame

requestAnimationFrame(function) 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画,也就是说更新动画的时机由浏览器决定

另外两个优势是:

CPU节能:页面隐藏(不可见),动画停止

浏览器优化:浏览器对requestAnimationFrame动画进行了优化

之前看了一些three.js,动画几乎都是使用requestAnimationFrame

结语

桃花坞里桃花庵,桃花庵下桃花仙。 桃花仙人种桃树,又摘桃花换酒钱!好生活啊!