setTimeout与setInterval
- Chrome中使用延迟队列保存Chrome内部的延时任务和setTimeout提交的延时任务。当执行完消息队列中的任务之后就会开始执行延时队列的处理函数,然后延时队列处理函数会根据发起时间和延迟时间计算出到期任务。
- setTimeout和setInterval不在JavaScript的规范中,由运行环境提供
- 如果当前任务执行时间过久,会影响到定时器的执行
- Chrome最小间隔1ms,存在嵌套会设置成4ms间隔时间
- 如果当前页面标签没有被激活,那么setTimeout的执行最小时间间隔是1s,目的是优化加载消耗和耗电量
- 时间间隔有最大值,当延时24.8天setTimeout就会溢出,致使延时函数被立即执行
- setTimeout执行的函数this对象指向window,可以通过匿名函数或者bind方法解决
- 对于每一个setInterval,队列中同时只能存在一个延时事件,后面的事件会被抛弃
requestAnimationFrame与requestIdleCallback
requestAnimationFrame: 告诉浏览器在下次重绘之前执行传入的回调函数(通常是操纵dom,更新动画的函数);由于是每帧执行一次,那结果就是每秒的执行次数与浏览器屏幕刷新次数一样,通常是每秒60次。
如果想要实现动画效果,每一次执行回调函数,必须要再次调用 requestAnimationFrame 方法;与 setTimeout 实现动画效果的方式是一样的,只不过不需要设置时间间隔。
let offsetTop = 0;const div = document.querySelector(".div");const run = () => {div.style.transform = `translate3d(0, ${offsetTop += 10}px, 0)`;window.requestAnimationFrame(run);};run();
在 requestAnimationFrame 之前,主要借助 setTimeout/ setInterval 来编写 JS 动画,而动画的关键在于动画帧之间的时间间隔设置,这个时间间隔的设置有讲究,一方面要足够小,这样动画帧之间才有连贯性,动画效果才显得平滑流畅;另一方面要足够大,确保浏览器有足够的时间及时完成渲染。
- requestIdleCallback: 会在浏览器空闲时间执行回调,也就是允许开发人员在主事件循环中执行低优先级任务,而不影响一些延迟关键事件。如果有多个回调,会按照先进先出原则执行,但是当传入了timeout,为了避免超时,有可能会打乱这个顺序。
代码
//practice1setTimeout(()=>{console.log(5)},5)setTimeout(()=>{console.log(4)},4)setTimeout(()=>{console.log(3)},3)setTimeout(()=>{console.log(2)},2)setTimeout(()=>{console.log(1)},1)setTimeout(()=>{console.log(0)},0)//practice2console.log(1)setTimeout(() => {console.log(2)new Promise(resolve => {console.log(4)resolve()}).then(() => {console.log(5)})})new Promise(resolve => {console.log(7)resolve()}).then(() => {console.log(8)})setTimeout(() => {console.log(9)new Promise(resolve => {console.log(11)resolve()}).then(() => {console.log(12)})})
