资讯专栏INFORMATION COLUMN

「JavaScript 定时器」setInterval、setTimeout和requestAnim

ghnor / 2079人阅读

摘要:大多数浏览器并没有精确到毫秒级别的触发事件,例如,我们设定某个函数在毫秒后执行,在老版本的中,这个函数至少会在毫秒以后执行。三实战光说不练假把式,现在我们就用上面介绍的三种定时器完成进度条的效果。

一.常见定时器
我们常见的定时器有以下两种

1. window.setTimeout 用于在指定的毫秒数后执行某段既定的代码
2. window.setInterval 用于每隔一段毫秒数重复执行既定的代码

这两个方法都可以通过手工设置时间来设定是多少毫秒后执行这段代码,或者是每隔多少毫秒执行这段代码。  

虽然我们期待浏览器按照我们设定的时间精确的执行代码,但是js却不能保证代码能恰好在那个时间点被运行,原因有两个。

大多数浏览器并没有精确到毫秒级别的触发事件,例如,我们设定某个函数在3毫秒后执行,在老版本的IE中,这个函数至少会在15毫秒以后执行。而在现代浏览器中,这个数值会短一点,但时间差一般也会超过1毫秒。

第二个原因与js的运行机制有关,具体见JavaScript 运行机制详解:再谈Event Loop.简单来说,就是js是一个单线程的解释器,一段时间只能执行一段代码,所以运行时分为主线程和任务队列两部分。而我们在定时器中设置的时间,仅代表1000毫秒后把这个任务插入到任务队列中,而此时必须要等到主线程的代码执行完毕,才能执行任务队列中的定时器的任务(在任务队列中也有调度,不一定第一个执行当前任务),因此时间是无法保证的。

二、requestAnimationFrame

那有没有时间准确的定时器呢?有一种选择是requestAnimationFrame. 示例如下:

 function animateMe(){
    requestAnimationFrame(function(){
      console.log(new Date());
      animateMe();
    })
}
animateMe();

这个api的原理是在由系统来决定回调函数的执行时机,在每一次系统绘制之前,会主动调用requestAnimationFrame中的回调函数,而频率也紧紧跟随浏览器的刷新频率。比如一般电脑的刷新频率通常为60Hz,即一秒钟重绘60次,那么回调函数就等于1000/60=16.7毫秒被执行一次,而如果刷新频率变为75Hz,那么这个时间就变为1000/75=13.3毫秒被执行一次。这样能保证回调函数在每一次绘制的间隔时间内只被执行一次,因此它的时间是可靠的。

三、实战

光说不练假把式,现在我们就用上面介绍的三种定时器完成进度条的效果。

1.setInterval

var timer;
$(".runBtn").click(function(){
    clearInterval(timer);
    $("#bar").width(0);
    timer = setInterval(function(){
      if($("#bar").width() < 500){
         $("#bar").width($("#bar").width()+5);
         $("#bar").text($("#bar").width()/5+"%");
      }else{
        clearInterval(timer);
      } 
    },16);
 });

点此预览效果

2.setTimeout

var timer;
$(".runBtn").click(function(){
    clearTimeout(timer);
    $("#bar").width(0);
    timer = setTimeout(function fn(){
      if($("#bar").width() < 500){
         $("#bar").width($("#bar").width()+5);
         $("#bar").text($("#bar").width()/5+"%");
         timer = setTimeout(fn,16);
      }else{
        clearTimeout(timer);
      } 
    },16);
 });

点此预览效果

3.requestAnimationFrame

var timer;
$(".runBtn").click(function(){
    cancelAnimationFrame(timer);
    $("#bar").width(0);
    timer = requestAnimationFrame(function fn(){
      if($("#bar").width() < 500){
         $("#bar").width($("#bar").width()+5);
         $("#bar").text($("#bar").width()/5+"%");
         requestAnimationFrame(fn);
      }else{
        cancelAnimationFrame(timer);
      } 
    });
 });

点此预览效果

四、最后

文章都来自本人的总结,难免有些纰漏,欢迎大家指正。一起学习,一起进步。如果觉得不错,欢迎点赞收藏嘤嘤嘤~~~

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/107692.html

相关文章

  • JavaScript 时器

    摘要:定时器方法相关方法有四种。返回值返回值是一个正整数,表示定时器的编号。这个值可以传递给来取消该定时器。使用方法很简单只有一个参数,该参数为您要取消定时器的标识符。用法很简单当代码运行到这行的时候,会取消所设置的定时器。 简单介绍在JavaScript中定时器有两个 setInterval() 与 setTime...

    王伟廷 评论0 收藏0
  • JS 异步的实现

    摘要:由于引擎同一时间只执行一段代码这是由单线程的性质决定的,所以每个代码块阻塞了其它异步事件的进行。这意味着浏览器将等待着一个新的异步事件发生。异步的任务执行的顺序是不固定的,主要看返回的速度。 我们经常说JS是单线程的,比如node.js研讨会上大家都说JS的特色之一是单线程的,这样使JS更简单明了,可是大家真的理解所谓JS的单线程机制吗?单线程时,基于事件的异步机制又该当如何,这些知识...

    sihai 评论0 收藏0
  • 细说 Javascript 拾遗篇(四) : setTimeout setInterval

    摘要:当间隔时间设置较小时,将会导致回调函数堆积。处理可能阻塞的代码最简单且最可控的方式就是在回调函数内部使用函数。但是很明显,由于指定最大值的限制,还会有定时器没有被清除掉。另外,尽量避免使用函数,从而避免可能导致的回调函数堆积现象。 由于 Javascript 是异步的,因此我们可以通过 setTimeout 和 setInterval 函数来指定特定时间执行代码。 function ...

    wangjuntytl 评论0 收藏0
  • javascript 时器工作原理

    摘要:说到中的定时器,我们肯定会想到和这两个函数。第一个回调一执行,又开启了第二个,这个定时器也是期望延时之后能够执行它的回调函数。可以用下面的图来概括总结上面对定时器执行原理进行了简要的分析,希望能够帮助我们更深入的理解。 说到 javascript 中的定时器,我们肯定会想到 setTimeout() 和 setInterval() 这两个函数。本文将从 事件循环(Event Loop)...

    godlong_X 评论0 收藏0
  • setTimeout-setInterval看JS线程

    摘要:提出标准,允许脚本创建多个线程,但是子线程完全受主线程控制,且不得操作。所以,这个新标准并没有改变单线程的本质。事件循环主线程线程只会做一件事,就是从消息队列里面取消息执行消息,再取消息再执行。工作线程是生产者,主线程是消费者。 最近项目中遇到了一个场景,其实很常见,就是定时获取接口刷新数据。那么问题来了,假设我设置的定时时间为1s,而数据接口返回大于1s,应该用同步阻塞还是异步?我们...

    elliott_hu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<