前端定时器

目录
  1. 1.定时器
    1. 1.1. setTimeout
    2. 1.2. setInterval
    3. 1.3. requestAnimationFrame
  2. 2. 标签动画

  前端开发中,会经常接到定时器的需求,倒计时计时器动画效果

  在博客- 标签页面中使用到了定时器来做::hover动画效果。接下来我会对比一下setTimeoutsetIntervalrequestAnimationFrame来实现定时器。

视频: 博客-标签

1.定时器

1.1. setTimeout

  setTimeout是JavaScript中的一个函数,用于在指定的延迟时间后执行一段代码或函数。它的工作原理是在指定的延迟时间后,将代码或函数放入JavaScript的事件队列中,等待当前代码执行完毕后再执行。

setTimeout的语法如下:

setTimeout(()=>||'func()',delay,[args...])

参数说明:

  • func|code:要执行的函数或代码。

  • delay:延迟时间,以毫秒为单位。

  • arg1, arg2, ...:可选参数,表示传递给函数的参数。

  当使用setTimeout时,它将在指定的延迟时间后执行一次函数或代码,然后返回一个定时器ID,可以使用clearTimeout()方法来取消定时器的执行。

  需要注意的是,setTimeout并不会立即执行函数或代码,而是在指定的延迟时间后放入事件队列中等待执行。如果当前的代码执行时间较长,或者存在其他的延迟操作,那么setTimeout中的函数或代码可能会在预期的时间之后才被执行。

示例:

function test(args){
console.log(args)
}
setTimeout(test,1000,['test','test1']);
setTimeout('test()',1000,['test','test1']);
cleatTimeout();

1.2. setInterval

  setInterval是JavaScript中的一个函数,用于在指定的时间间隔后重复执行一段代码或函数。它的工作原理是在指定的时间间隔后,将代码或函数放入JavaScript的事件队列中,等待当前代码执行完毕后再执行。

setInterval的语法如下:

setInterval(()=>||'func()',delay,[args...])

参数说明:

  • func|code:要执行的函数或代码。

  • delay:时间间隔,以毫秒为单位。

  • arg1, arg2, ...:可选参数,表示传递给函数的参数。

  当使用setInterval时,它将在指定的时间间隔后重复执行函数或代码,直到调用clearInterval()方法来停止执行。与setTimeout不同的是,setInterval会持续不断地重复执行函数或代码,直到被明确停止。

  需要注意的是,setInterval并不会立即执行函数或代码,而是在指定的时间间隔后放入事件队列中等待执行。如果当前的代码执行时间较长,或者存在其他的延迟操作,那么setInterval中的函数或代码可能会在预期的时间之后才被执行。

示例:

function test(args){
console.log(args)
}
setInterval(test,1000,['test','test1']);
setInterval('test()',1000,['test','test1']);
clearInterval();

1.3. requestAnimationFrame

  requestAnimationFrame是Web动画API的一部分,用于在浏览器下一次重绘之前调用指定的回调函数,从而实现平滑的动画效果。与setTimeout和setInterval相比,requestAnimationFrame具有更高的性能和更好的用户体验。

requestAnimationFrame的语法如下:

requestAnimationFrame(callback);

参数说明:

  • callback:要执行的回调函数。

  当使用requestAnimationFrame时,它会返回一个唯一的ID,可以使用这个ID来取消动画帧的调用。与setTimeout和setInterval不同的是,requestAnimationFrame的回调函数将在浏览器下一次重绘之前执行,而不是简单地等待指定的时间后执行。这样可以充分利用浏览器的重绘机制,实现更平滑的动画效果。

  requestAnimationFrame的优势在于它能够根据浏览器的刷新率来同步动画,避免了由于不同的屏幕刷新率和硬件配置导致的动画卡顿和闪烁。同时,它也避免了在动画过程中不必要的重绘和计算,提高了动画的性能和响应性。

  使用requestAnimationFrame时需要注意,它只会在浏览器处于激活状态时执行回调函数。如果浏览器处于最小化或隐藏状态,那么回调函数将不会被执行。因此,在使用requestAnimationFrame时,需要确保浏览器处于激活状态,或者在回调函数中添加适当的逻辑来处理浏览器不处于激活状态的情况。

示例:

function frame(){
console.log('frame')
}
requestAnimationFrame(frame);

2. 标签动画

  使用 requestAnimationFrame 可以替代 setInterval 来实现定时任务,因为 requestAnimationFrame 更加高效,能够根据屏幕刷新率来同步动画,避免了不必要的重绘和计算。

下面是使用 requestAnimationFrame 实现 setInterval 更新博客- 标签的示例代码:

/***
* 兼容不支持requestAnimationFrame的浏览器
***/
window.requestAnimationFrame = (function () {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||/* Safari 和 Chrome */
window.mozRequestAnimationFrame ||/* Firefox */
window.oRequestAnimationFrame ||/* Opera */
window.msRequestAnimationFrame ||/* IE 9 */
function (callback) {
window.setTimeout(callback, 6000 / 60)
}
})();
window.cancelAnimationFrame = (function () {
return window.cancelAnimationFrame ||
window.webkitCancelAnimationFrame ||
window.mozCancelAnimationFrame ||
window.oCancelAnimationFrame ||
window.msCancelAnimationFrame || clearTimeout
})();


/**
* 设置精度定时器
* @param {function} 回调函数
* @param {number} 延迟时间
* @return {number} 定时器ID
*/
function setIntervalPrecision(callback, delay) {
// 生成并记录定时器ID
let obj = window.interValPrecisionObj || (window.interValPrecisionObj = { num: 0 })
obj.num++
obj['n' + obj.num] = true
var intervalId = obj.num
// 开始时间
var startTime = +new Date()
// 已执行次数
var count = 0
// 延迟时间
delay = delay || 0


;(function loop() {
// 定时器被清除,则终止
if (!obj['n' + intervalId]) return

// 满足条件执行回调
if (+new Date() > startTime + delay * (count + 1)) {
count++
callback(count)
}

window.requestAnimationFrame(loop)
})()

return intervalId
}

/**
* 清除精度定时器
* @param {number} 定时器ID
*/
function clearIntervalPrecision(intervalId) {
if (window.interValPrecisionObj) {
window.cancelAnimationFrame('n' + intervalId)
delete window.interValPrecisionObj['n' + intervalId]
}
}
//loopHover 自己的业务实现
setIntervalPrecision(loopHover, 100)
26.1k