浅析javascript三种定时器原理和异同

Posted 十九万里

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅析javascript三种定时器原理和异同相关的知识,希望对你有一定的参考价值。

念念不忘 必有回想

前言

众所周知js定时器有两种 setTimeout和setInterval 还有一个新增的requeTanimationFrame(动画API)也被加入到了面试经常考察的范围,那么我就从是什么 怎么用,什么时候用,他们的区别是什么来简述一下这三者的关系

1、setTimeout(延时器)

setTimeout完整的写法其实是window.setTimeout 是window的一个属性,由于window是全局作用域,通常我们写的时候就省略了

setTimeout()方法用来指定某个函数或字符串在指定的毫秒数之后执行它返回一个整数,表示定时器的编号,这个值可以传递给clearTimeout()用于取消这个函数的执行

setTimeout有两个参数,第一个是function:表示将要执行的函数或者代码,这里可以
第二个参数delay是推迟执行的毫秒数。如果省略就是马上执行

在ie9以下 只允许setTimeout执行两个参数
ie9以上可以多个参数
还有一个不常用的第三个参数:
在MDN中是这样解释的
在这里插入图片描述

清除setTimeout方法:
setTimeout()对应的是 clearTimeout(id);

2、setInterval (定时器)

同样 setInterval也是window上的方法,window被省略

setInterval() 方法重复调用一个函数或执行一个代码段,在每次调用之间具有固定的时间延迟。

每次调用都有固定的时间间隔,会返回一个时间间隔ID 该ID唯一地标识时间间隔,在清除定时器的时候就调用此ID来清除。

同样的 setInterval和setTimeout的参数相同都是三个

function code
delay
arg1, …, argN 可选
这里我就不重复了

清除定时器的方法:

setInterval()对应的是 clearInterval(id);

一个小问题:setInterval有什么缺点呢:

1.不去关心回调函数是否还在运行
在某些情况下,函数可能需要比间隔时间更长的时间去完成执行。比如说是用setInterval每隔5秒对远端服务器进行轮询,网络延迟,服务器无响应以及其他因素将会阻止请求按时按成。结果会导致返回一串无必要的排成队列请求。
2.忽视错误
因为某些原因,setInterval调用的代码中会出现一个错误,但是代码并不会中止执行而是继续执行错误的代码。
3.缺乏灵活性
除了前面提到的缺点之外,我非常希望setInterval方法能有一个表明执行次数的参数而不是无休止的执行下去。

3、requeTanimationFrame(动画API)

这个点我也是在复习面试的时候发现的
先来看MDN怎么解释这个API的

window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行>

会返回一个callback参数
下一次重绘之前更新动画帧所调用的函数(即上面所说的回调函数)。该回调函数会被传入DOMHighResTimeStamp参数,该参数与performance.now()的返回值相同,它表示requestAnimationFrame() 开始去执行回调函数的时刻。

也就是说 requeTanimationFrame不需要设置时间间隔,大多数电脑显示器的刷新频率是60hz,大概相当于每秒钟重绘60次,大多数浏览器都会对重绘操作加以限制,不炒股欧显示器的重绘频率,一次超过显示屏频率用户体验也不会提升,所以最佳循环事件是1000ms/60,约等于16.6ms

特点:
requestAnimationFrame会把每一帧中所有的DOM操集中起来,在一次重绘或者回流中完成,并且重绘或回流的时间间隔会紧紧跟随浏览器的刷新频率
在隐藏或者不可见的元素中,requestAnimationFrame将不会进行重绘,这就意味着更少的cpu GPU和内存的使用量
requestAnimationFrame是由浏览器专门为提供的api 在运行的时候浏览器会自动优化方法的调用,并且如果页面不是激活状态的话,动画会自动暂停,有效节省了CPU的开销。
官网文档地址

4、这三个方法什么时候应用

setTimeout用于延迟执行某方法或功能
setInterval则一般用于刷新表单,对于一些表单的假实时指定时间刷新同步

5、setInterval和setTimeout的区别

1、setTimeout在规定的时间后使用一次就停止操作了
setInterval会按照这个规定的时间一直循环下去

2、两种定时器清除方法不一样
setInterval()对应的是 clearInterval(id);
setTimeout()对应的是 clearTimeout(id);

6、使用setTimeout实现setInterval

原理:

在setTimeout内部调用function的时候再次调用setTimeout方法 实现循环定时达到setInterval的效果

代码实现:
简单版本:

setTimeout(function(){

     //do something 

     setTimeout(arguments.callee,interval);

},interval)

复杂版本:

function interval(func, w, t){
var interv = function(){
if(typeof t === “undefined” || t-- > 0){
setTimeout(interv, w);
try{
func.call(null);
}
catch(e){
t = 0;
throw e.toString();
}
}
};
setTimeout(interv, w);
};
这个interval函数有一个叫做inter的内部函数,它通过setTimeout来自动被调用,在inter中有一个闭包,它检查了重复次数,调用了回调函数并通过setTimeout再次调用了interv。万一回调函数中出现了一个异常,interv调用将会终止,异常也会被抛出。
当然不能保证函数在固定的间隔中执行,但是它保证新的区间开始时上一个区间中的函数已经执行完毕,我认为这是非常重要的。

那么问题也来了,使用setTimeout实现setInterval和 setInterval有什么区别呢

setTimeout(fn, time),超时调用,在时间大于等于 time 时调用;
setInterval(fn, time),是间歇调用,每隔 time 调用一次。
使用setInterval()创建的定时器确保了定时器代码规则地插入队伍中。问题在于:如果定时器代码在代码再次添加到队列之前还没完成执行,结果就会导致定时器代码连续运行好几次。而之间没有间隔。不过幸运的是:javascript引擎足够聪明,能够避免这个问题。当且仅当没有该定时器的如何代码实例时,才会将定时器代码添加到队列中。这确保了定时器代码加入队列中最小的时间间隔为指定时间。
这种重复定时器的规则有两个问题:

  1. 某些间隔会被跳过
    2 多个定时器的代码执行时间可能会比预期小。

以上是关于浅析javascript三种定时器原理和异同的主要内容,如果未能解决你的问题,请参考以下文章

定时器的使用和原理浅析,alarm/sleep函数

JavaScript声明全局变量三种方式的异同

JavaScript中constvar和let区别浅析

浅析ajax原理与用法

浅析redis与zookeeper构建分布式锁的异同

浅析Java重写(Override)与重载(Overload)的异同