热点新闻
requestAnimationFrame和requestIdleCallback是宏任务还是微任务
2023-07-04 14:00  浏览:1540  搜索引擎搜索“早勤网”
温馨提示:信息一旦丢失不一定找得到,请务必收藏信息以备急用!本站所有信息均是注册会员发布如遇到侵权请联系文章中的联系方式或客服删除!
联系我时,请说明是在早勤网看到的信息,谢谢。
展会发布 展会网站大全 报名观展合作 软文发布





一、思考

大家都知道异步任务分为宏任务和微任务,不知道的可以看我的另一篇文章(深入理解Event Loop的运行机制)
要搞清楚requestAnimationframe和requestIdleCallback是宏任务还是微任务就必须要搞清楚下面几个问题:

  1. 浏览器在每一轮Event Loop事件循环中都会去渲染屏幕吗?
  2. requestAnimationframe在哪个阶段执行,是在渲染前还是渲染后?是在微任务执行前还是执行后?
  3. requestIdleCallback在哪个阶段执行,是在渲染前还是渲染后? 是在微任务执行前还是执行后?

二、任务的执行时机

在浏览器的Event Loop中是有多个任务队列的,每个任务队列的执行时机是不一样的,下面直接上干货,说说浏览器执行任务的顺序

  1. 从task任务队列中取第一个task(比如setTimeout、setIntervel的回调,也可以将同一轮循环中的所有同步代码看作是一个宏任务),执行它。
  2. 执行微任务队列里的所有微任务。
  3. 浏览器判断是否更新渲染屏幕,如果需要重新绘制,则执行步骤4-13,如果不需要重新绘制,则流程回到步骤1,这样不断循环。
  4. 触发resize、scroll事件,建立媒体查询(执行一个任务中如果生成了微任务,则执行完任务该后就会执行所有的微任务,然后再执行下一个任务)。
  5. 建立css动画(执行一个任务中如果生成了微任务,则执行完该任务后就会执行所有的微任务,然后再执行下一个任务)。
  6. 执行requestAnimationframe回调(执行一个任务中如果生成了微任务,则执行完该任务后就会执行所有的微任务,然后再执行下一个任务)。
  7. 执行 IntersectionObserver 回调(执行一个任务中如果生成了微任务,则执行完该任务后就会执行所有的微任务,然后再执行下一个任务)。
  8. 更新渲染屏幕。
  9. 浏览器判断当前帧是否还有空闲时间,如果有空闲时间,则执行步骤10-12。
  10. 从 requestIdleCallback回调函数队列中取第一个,执行它。
  11. 执行微任务队列里的所有微任务。
  12. 流程回到步骤9,直到requestIdleCallback回调函数队列清空或当前帧没有空闲时间。
  13. 流程回到步骤1,这样不断循环。

三、代码验证

我们可以写一些代码到Chrome浏览器中验证一下,看看requestAnimationframe和requestIdleCallback的执行顺序是怎样的。

运行以下这段代码

requestAnimationframe(()=>{ console.log(111); setTimeout(() => { console.log(222); }); Promise.resolve().then(() => { console.log(333); }); }) requestAnimationframe(() => { console.log(444); Promise.resolve().then(() => { console.log(555); }); })

输出结果





运行以下这段代码

requestIdleCallback(() => { console.log(111); setTimeout(() => { console.log(222); }) Promise.resolve().then(() => { console.log(333); }) }) requestIdleCallback(() => { console.log(444); Promise.resolve().then(() => { console.log(555); }) })

输出结果





运行以下这段代码

Promise.resolve().then(() => { console.log(111); setTimeout(() => { console.log(222); }) Promise.resolve().then(() => { console.log(333); }) }) Promise.resolve().then(() => { console.log(444); Promise.resolve().then(() => { console.log(555); }) })

输出结果




四、总结

  1. requestAnimationframe和requestIdleCallback是和宏任务性质一样的任务,只是他们的执行时机不同而已。也有人说它们既不是宏任务也不是微任务,其实我们不必纠结这个,我们所要做的就是知道他们的执行时机就好。
  2. 浏览器在每一轮Event Loop事件循环中不一定会去重新渲染屏幕,会根据浏览器刷新率以及页面性能或是否后台运行等因素判断的,浏览器的每一帧是比较固定的,会尽量保持60Hz的刷新率运行,每一帧中间可能会进行多轮事件循环。
  3. requestAnimationframe回调的执行与task和microtask无关,而是与浏览器是否渲染相关联的。它是在浏览器渲染前,在微任务执行后执行。
  4. requestIdleCallback是在浏览器渲染后有空闲时间时执行,如果requestIdleCallback设置了第二个参数timeout,则会在超时后的下一帧强制执行。

更多个人文章

  1. 两个跨域页面进行跳转传参的终极方案
  2. 彻底搞懂盒子模型
  3. hashHistory和browserHistory的区别
  4. 面试秘籍之手写系列
  5. 十分钟带你入门Chrome插件开发
发布人:5bc5****    IP:101.229.35.***     举报/删稿
展会推荐
让朕来说2句
评论
收藏
点赞
转发