rAF在EventLoop的表现

最近会被问到EventLoop的相关问题,这个只要对任务微任务理解到位一般没啥问题,但有次被问到“requestAnimation的执行时机是什么”,答约:“rAF是在浏览器重新渲染屏幕之前执行”,之后被追问:“那它属于宏任务还是微任务,他在时间循环的执行时机是什么样的”。

当时听到这个问题一时有点懵,因为按照之前的经验和理解,rAF一般做动画场景很少遇到宏任务微任务的问题,我感觉它跟宏任务微任务是没啥关系的,因为我看过MDN HTML5的规范关于‘Task’和‘Microtask’的划分,是没看到它的身影的。下来后研究了下,比如下面这段代码,大家可以猜猜输出什么:

setTimeout(() => {
    console.log('setTimeout');
}, 0);
Promise.resolve()
    .then(() => {
        console.log(2);
    })
    .then(() => {
        console.log(3);
    });
new Promise((resolve) => {
    console.log(4);
    resolve();
})
    .then(() => {
        console.log(5);
        return 6;
    })
    .then(Promise.resolve(7))
    .then((res) => {
        console.log(res);
    });
// setTimeout(() => {
//     console.log('setTimeout2');
// });
requestAnimationFrame(() => {
    console.log('animation’');
});

你输入到浏览器,看到输出可能是:

4 2 5 3 6  animation setTimeout

这时候你是不是就把rAF归为微任务了?那你再执行的同时,滚动下浏览器,会发现输出变不一样了,变成了:

4 2 5 3 6  setTimeout animation

此时把注释打开,再加一个宏任务,执行同时滚动浏览器,发现输出

4 2 5 3 6  setTimeout setTimeout2 animation

这时,你就会发现rAF的表现又有点像last task的表现。

对这种现象,我归结表现为:
如果不滚动屏幕,不需要重新绘制帧,requestAnimationFrame会在下一个宏任务之前伴随着本轮微任务执行(顺序也会按照微任务队列的顺序),,即输出’setTimeout’,‘animation’
如果发生了滚动事件,需要重新绘制屏幕,animation最后执行.就算再加一个setTimeout宏任务,还是同理的表现。

查了不少资料,国内的很多要么没解释清楚要么瞎解释,外网stackOverFlow上有一些讨论,国内的推荐看这篇 链接,感觉还是要朝着源码和规范去理解,但其实最后浏览器差异和版本的差异表现还有不同(比如rIC的执行在chrome不同版本的执行。。)。

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值