• 全国 [切换]
  • 二维码
    早勤网

    手机WAP版

    手机也能找商机,信息同步6大终端平台!

    微信小程序

    微信公众号

    当前位置: 首页 » 行业新闻 » 热点新闻 » 正文

    requestAnimationFrame和requestIdleCallback是宏任务还是微任务

    放大字体  缩小字体 发布日期:2020-01-06 14:00:11   浏览次数:1214  发布人:5bc5****  IP:101.229.35.***  评论:0
    导读

    一、思考 大家都知道异步任务分为宏任务和微任务,不知道的可以看我的另一篇文章(深入理解Event Loop的运行机制) 要搞清楚requestAnimationFrame和requestIdleCallback是宏任务还是微任务就必须要搞清楚下面几个问题:浏览器在每一轮Event Loop事件循环中都会去渲染屏幕吗? requestAnimationFrame在哪个阶段执行,是在渲染前还是渲染后?






    一、思考

    大家都知道异步任务分为宏任务和微任务,不知道的可以看我的另一篇文章(深入理解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**** 发布的作品,本文仅代表发布者个人观点,本站未对其内容进行核实,请读者仅做参考,如若文中涉及有违公德、触犯法律的内容,一经发现,立即删除,发布者需自行承担相应责任。涉及到版权或其他问题,请及时联系我们154208694@qq.com删除,我们积极做(权利人与发布者之间的调停者)中立处理。郑重说明:不 违规举报 视为放弃权利,本站不承担任何责任!
    有个别老鼠屎以营利为目的遇到侵权情况但不联系本站或自己发布违规信息然后直接向本站索取高额赔偿等情况,本站一概以诈骗报警处理,曾经有1例诈骗分子已经绳之以法,本站本着公平公正的原则,若遇 违规举报 我们100%在3个工作日内处理!
    0 条相关评论
     

    (c)2008-现在 zaoqin.com All Rights Reserved.