requestAnimationFrame()
执行动画,要求浏览器在下次重绘之前调用指定的回调函数更新动画
参数:回调函数作为参数,回调函数会在下次重绘之前执行
回调函数的执行次数和浏览器的刷新频率有关
返回值: 回调列表的唯一ID标识;传入window.cancelAnimationFrame()
取消回调函数
可以利用requestAnimationFrame()
实现节流
let flag = false;
window.addEventListener('scroll',()=>{
if(!flag){
requestAnimationFrame(callback);
flag = true;
// 计时器可以操作实际的执行间隔
setTimeout(() => flag = false, 50);
}
})
setTimeout计时器
: 时间到期之后,执行该段代码
setInterval定时器
: 是指定何时将回调函数放入执行队列,但是没有指定什么时候执行;
requestAnimationFrame
由系统回调函数的执行时间,保证回调函数在刷新间隔中执行一次,不会出现丢帧、卡顿的情况;
一般电脑的刷新频率是60HZ
,也就是每秒重绘60次,大约17毫秒刷新一次;
setTimeout
:
- 回调函数的执行时间不确定,主线程中没有任务执行的时候,才会检查执行该队列中的任务
- 与屏幕的刷新频率没有关系
- 在内存中对元素属性进行修改,然后渲染的屏幕上,如果setTimeout回调函数未执行,屏幕绘制了或者是屏幕还未绘制,但是
setTimeout
回调函数执行了,这两种情况就会出现掉帧、画面卡顿
设置0ms延时:
// 设置延迟0ms
setTimeout(callback,0);
注: 尽可能立即执行,但是如果嵌套调用setTimeout次数(5次以上)的话,就会设置为4ms(chrome和Firefox);未被激活的tabs,setTimeout最小延迟是1s(1000ms)
setInterval
:
setTnterval(callback,delay)
: callback中函数的执行时间,超过delay;函数之间就没有间隔执行; 也可能出现有的被跳过执行的情况
let index = 0;
let timerid = setInterval(() => {
if(++index === 10) clearInterval(timerid);
console.log('执行时间:',performance.now());
}, 1000);
下面是保存的执行结果:
执行时间: 1084.725000000617
执行时间: 2084.6200000014505
执行时间: 3084.69000000332
执行时间: 4084.7300000023097
执行时间: 5084.780000004685
执行时间: 6084.815000001981
执行时间: 7083.890000001702
执行时间: 8083.904999999504
执行时间: 9083.995000000868
执行时间: 10083.944999998494
执行的时间间隔是一次要比1000ms短
用setTimeout
实现setInterval
setTimeout(function setInterval2(){
setTimeout(setInterval2,2000);
},2000);
每个1s打印从from-to的值:
setInterval实现
function print(from, to) {
let current = from;
let timerId = setInterval(function() {
alert(current);
if (current === to) clearInterval(timerId);
current++;
},1000);
}
setTimeout实现
function print(from, to) {
let current = from;
setTimeout(function go(){
alert(current);
if (current < to) {
setTimeout(go, 1000);
}
current++;
},1000);
}
requestAnimationFrame
优势:
- CPU节能:
setTimeout
,当页面隐藏或最小化的时候,还是会在后台运行,此时刷新动画没用,但是requestAnimationFrame
和系统保持同步,页面未激活的状态下,requestAnimationFrame
会停止执行;页面激活,会从上次停止的位置开始执行; - 函数节流:
resize
、scroll
、拖拽
事件中,避免在函数执行间隔内,函数多次执行。
参考文章:
【1】window.requestAnimationFrame
【2】window.setTimeout
【3】window.setInterval
【3】从打字机效果的 N 种实现看JS定时器机制和前端动画
【4】Scheduling: setTimeout and setInterval