前端定时器详解
一、简介
JS是单线程,同一时间只能执行一个任务,其他任务就得排队,后续任务必须等到前一个任务结束才能开始执行。而有时候我们需要规定时间内做一件事,比如倒计时、页面轮播图等;这个时候就需要用到JS定时器。
当我们定义了一个定时器后,定时器会进入浏览器的定时器触发线程去排队,时间到了之后再转回到JS执行线程中排队。下面就介绍JS的几种定时器:
二、定时器
2.1 setTimeout(fn,time,lang)
在规定时间内执行一次,是一次性的。
- fn是时间到了要执行的js代码串;
- time执行代码钱需要等待的毫秒数;
- lang可选,设置脚本语言JScript | VBScript | JavaScript(历史遗留问题可忽略此参数)
每次执行定时器函数会返回一个id,用于清除定时器:clearTimeout(timerId)
示例:
var timerId = setTimeout(function () {
console.log("1秒钟到了");
clearTimeout(timerId);
}, 1000);
2.2 setInterval(fn,time,lang)
在规定时间内执行,是周期性的。
- fn是时间到了要执行的js代码串;
- time执行代码钱需要等待的毫秒数;
- lang可选,设置脚本语言JScript | VBScript | JavaScript(历史遗留问题可忽略此参数)
每次执行定时器函数会返回一个id,用于清除定时器:clearInterval(timerId)。只有清除这个定时器之后才会停止定时,否则便会一直执行。
示例:
var index = 0;
var timerId = setInterval(function () {
console.log(++index + "秒钟到了");
if(index === 10) {
clearInterval(timerId); // 十秒的时候结束运行
}
}, 1000);
2.3 requestAnimationFrame(fn)
触发间隔跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。默认只会执行一次,只需要传递fn执行代码串。清除定时器:cancelAnimationFrame(timerId)
这个是HTML5新增的特性,可以利用这个来做无限循环的动画,相比较setTimeout、setInterval的优势在于:
- 它会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,提升性能;
- 在隐藏或不可见的元素中,它不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。
requestAnimationFrame(function() {
console.log("屏幕刷新了!");
});
注意:requestAnimationFrame是新增的属性需要考虑兼容性,无法设置规定时间平常使用较少。
三、封装定时器类
在平常项目中很多地方都会用到这个定时功能,但是不能很好的清除对应定时器,导致事件不听调用,影响性能。当定义一个工具类后便可以轻松的创建一个定时任务,关闭时也不用担心定时id无法获取的问题。
class MyTimer {
constructor() {
this.timerId = undefined;
}
timeout(fn, time) {
if(this.timerId) {
clearTimeout(this.timerId)
}
setTimeout(fn, time);
setInterval()
}
interval(fn, time) {
if(this.timerId) {
clearInterval(this.timerId)
}
setInterval(fn, time);
}
}
这里就是简单封装了一下,保证new的一个定时器都有唯一的一个id值;具体的封装需要根据业务场景来决定。
四、总结
-
主要定时器误差问题,受事件循环机制影响;
-
根据不同需求选择对应定时器;
-
用变量保存定时器返回的id(清除时用到);
-
使用定时器时一定要先清除之前的定时器,避免定时器叠加;