背景: 因为 JS 是单线程执行的,如果前面的代码影响了性能,就会导致 setInterval或setTimeout
不会按期执行。
1. 为什么可以用requestAnimationFrame
由于 requestAnimationFrame
自带函数节流功能,基本可以保证在 16.6 毫秒内只执行一次,并且该函数的延时效果是精确的,没有其他定时器时间延迟不准确的问题。
2. 使用requestAnimationFrame
实现定时器
/**
* 使用 requestAnimationFrame 实现的 setInterval 函数
* @callback callback - 需要周期性执行的回调函数
* @param {number} interval - 时间间隔,单位为毫秒
* @returns {number} - 返回定时器的引用
*/
function setInterval(callback, interval) {
let timer
const now = Date.now
let startTime = now()
let endTime = startTime
// 定义一个循环函数,用于更新定时器
const loop = () => {
// 重新设置定时器,以保持循环执行
timer = window.requestAnimationFrame(loop)
endTime = now()
// 如果经过的时间超过了时间间隔,执行回调函数并重新开始计时
if (endTime - startTime >= interval) {
startTime = endTime = now()
callback(timer)
}
}
// 第一次启动循环
timer = window.requestAnimationFrame(loop)
return timer
}
3. 使用定时器
let a = 0
// 创建一个每 1000 毫秒执行一次的定时器
setInterval(timer => {
console.log(1)
a++
if (a === 3) {
// 取消定时器
cancelAnimationFrame(timer)
}
}, 1000)
4. 交流
欢迎使用requestAnimationFrame
来实现setTimeout