关闭

JavaScript定时器原理及高级使用

2779人阅读 评论(0) 收藏 举报

javaScript里面内置了两个定时器,一个是setTimeout()一个是setInterval()。下面将由浅入深来理解一下定时器的工作原理。

使用方式:

setTimeout()

setTimeout 的语法非常简单,第一个参数为回调函数,第二个参数为延时的时间。函数返回一个数值类型的ID唯一标示符,此ID可以用作 clearTimeout 的参数来取消定时器:
function out(){
	alert("定时器");
 };
var timeoutID = window.setTimeout(out,10000);
第一个参数可以传入多个回调函数中间以";"隔开即可,另外要注意的是函数不能加(),不能写成out();否则就会有意想不到的错误。

setInterval()

该方法使得一个函数每隔固定时间被调用一次,是一个很常用的方法。如果想要取消定时执行,和clearTimeout方法类似。
第一个方法和第二个方法的最大差别是一个是只执行一次,一个是会循环执行。
高级定时器
很多人都对JS的定时器存在普遍的误解,认为它是线程,其实JavaScript是运用于单线程的环境中的,定时器仅仅只是计划代码再未来的某个时间执行。执行时机是不能保证的,因为在页面的生命周期中,不同时间可能有其他代码在控制JavaScript线程。在页面下载完成后的代码运行,事件处理程序,Ajax回调函数都必须使用同样的线程来执行,实际上,浏览器负责进行排序,指派某段代码在某个时间点的优先级。
可以把JS想象成在时间线上运行的,当页面载入时,先执行任何包含在<script>元素的代码,在这之后,JS进程将等待更多代码执行。当进程空闲的时候,下一个代码会被触发并立刻执行。例如当点击某个按钮时,onclick事件处理程序会立刻执行,只要JavaScript进程处于空闲状态。

除了主JS执行程序外,还有一个进程空闲时候执行的代码队列,随着页面在其生命周期中的推移,代码会按照执行顺序添加到队列。
定时器对队列的工作方式是,当特定的时间过去后,将代码插入,注意添加到队列并不意味着它会马上执行,而只能说它会尽快执行,设定一个250ms后执行的定时器,不代表250ms后它会马上执行,它只会表示在150ms后被加入到队列中,如果这个时间点队列是空闲的,那么这段代码就会被执行。
var timeoutID = window.setTimeout(out,10000);
var btn = document.getElementById("mybtn");
    btn.onclick = function () {
        setTimeout(function () {
            document.getElementById("message").nodeName = "mymessage";
            //其它代码
        }, 250);
    }


对于定时器最要注意的是:指定的时间间隔表示何时将定时器的代码添加到队列中,而不是何时执行代码。关于这个onclick事伯处理的进程时间线请看下图:


下面展示一个简单的计时,并带有停止功能:
<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="">
  <meta name="Keywords" content="">
  <meta name="Description" content="">
  <title>Document</title>
 </head>
 <body>
<input type="button" value="开始计时!" onClick="timedCount()">
<input type="text" id="txt">
<input type="button" value="停止计时!" onClick="stopCount()">
 </body>
<script type="text/javascript">
    var c = 0
    var t
    function timedCount() {
        document.getElementById('txt').value = c
        c = c + 1
        t = setTimeout("timedCount()", 1000)
    }
 
    function stopCount() {
        clearTimeout(t)
    }
</script>
</html>


关于重复定时器,我们既可以使用setTimeout来重复创建就时器,也可以直接用setInterval,使用setInterval创建的定时器确保了定时器规则地插入队列中,这个方式问题在于代码可能在再次添加到队列之前还没有完成执行,可能寻到定时器重复运行好几次,而中间没有停顿,然而现在的javascript引擎很聪明,能避免这个问题,当使用setInterval时,仅当没有定时器的任何其它代码时,才将定时器代码添加到队列中,这样会确保定时器代码加入到队列的时间的间隔是为指定的间隔,请注意这只是加入队列的时间间隔,并不是执行代码的时间间隔,所以使用setInterval还是会存在两个问题:(1)某些间隔会被跳过了(2)多个定时器的代码执行间隔可能会比预期的要小。

这个例子中的第一个定时器是在205处添加到队列中,但是直到了300ms处才能够执行。当执行这个定时器代码时,在405处又给队列添加了另外一个副本,在下一个间隔,即605ms处,第一个定时器代码仍然在执行,同时在队列中已经有了一个定时器代码的实例。结果是在5ms添加的定时器代码结束之后,405处添加的定时器代码就立刻执行。

为避免这些问题,可以使用如下模式使用链式setTimeout调用:
setTimeout(function () {
        //处理中
        setTimeout(arguments.callee, interval);
    }, interval)

关于定时器的使用技巧

给定时器调用传递参数

无论是window.setTimeout还是window.setInterval,在使用函数名作为调用句柄时都不能带参数,而在许多场合必须要带参数,这就需要想方法解决。例如对于函数hello(_name),它用于针对用户名显示欢迎信息: 
var userName="jack"; 
//根据用户名显示欢迎信息 
function hello(_name){ 
      alert("hello,"+_name); 
} 

这时,如果企图使用以下语句来使hello函数延迟3秒执行是不可行的: 
window.setTimeout(hello(userName),3000); 
这将使hello函数立即执行,并将返回值作为调用句柄传递给setTimeout函数,其结果并不是程序需要的。而使用字符串形式可以达到想要的结果: 
window.setTimeout("hello(userName)",3000); 
这里的字符串是一段JavaScript代码,其中的userName表示的是变量。但这种写法不够直观,而且有些场合必须使用函数名,下面用一个小技巧来实现带参数函数的调用: 
<script language="JavaScript" type="text/javascript"> 
<!-- 
var userName="jack"; 
//根据用户名显示欢迎信息 
function hello(_name){ 
       alert("hello,"+_name); 
} 
//创建一个函数,用于返回一个无参数函数 
function _hello(_name){ 
       return function(){ 
             hello(_name); 
       } 
} 
window.setTimeout(_hello(userName),3000); 
//--> 
</script> 
这里定义了一个函数_hello,用于接收一个参数,并返回一个不带参数的函数,在这个函数内部使用了外部函数的参数,从而对其调用,不需要使用参数。在 window.setTimeout函数中,使用_hello(userName)来返回一个不带参数的函数句柄,从而实现了参数传递的功能。 

取消定时器

一般我们取消定时器是用的
clearInterval(Method); 
可是读了上面的内容我们知道它是不会马上执行的,所以优化方案如下
var timeout = false; //启动及关闭按钮  
function time()  
{  
  if(timeout) return;  
  Method();  
  setTimeout(time,100); //time是指本身,延时递归调用自己,100为间隔调用时间,单位毫秒  
} 

建议:最好不用setInterval,而用setTimeout的延时递归来代替interval。

setInterval会产生回调堆积,特别是时间很短的时候。  





1
0
查看评论

Javascript中定时器的使用方法

项目中,经常会用到定时器来实现数据实时更新、时间等,简单总结一下: Javascript中的定时器有两种,setInterval和setTimeout,而定时器的作用就是延迟执行。 一、定时器的写法 setInterval(expression,milliseconds); setTimeou...
  • lvkelly
  • lvkelly
  • 2017-01-04 17:38
  • 2057

javascript定时器,取消定时器,及js定时器优化方法

通常用的方法: 启动定时器: window.setInterval(Method,Time) Method是定时调用的js方法 Time是间隔时间,单位是毫秒 取消定时器: clearInterval(Method); 那么问题来了。用 clearInterval...
  • johnstrive
  • johnstrive
  • 2014-12-28 19:08
  • 90391

javascript定时器及其优化

启动定时器 method是调用的js方法 time是时间间隔,毫秒数 关闭定时器 用这种方法去关闭定时器,往往不能及时关闭。setInterval会产生回调堆积,特别是时间较短的情况下 解决方法如下: 在JavaScript中还有另一种定时器,setTimeout(method,time),与...
  • l505_
  • l505_
  • 2016-07-28 11:41
  • 300

JavaScript中定时器使用

1 setTimeout() setTimeout函数用来指定某个函数或某段代码,在多少毫秒之后执行。它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器。 var timerId = setTimeout(func|code, delay) 上面代码中,setTimeout函数接受两...
  • jasonzds
  • jasonzds
  • 2016-12-17 22:12
  • 1939

JS 定时器工作原理

在对JS本质理解的层面上,重要的是了解JS定时器是如何工作的。很多时候我们觉得定时器的执行不够直观, 那因为它们运行在单线程的环境里。我们先来仔细观察下面三个js的内置函数,然后我们再具体去使用它们: 1.var id= setTimeout(fn,delay); ...
  • atgwwx
  • atgwwx
  • 2013-01-06 14:16
  • 2103

js 中定时器的写法

在js 中定时 一般会用到setTimeout 和 setInterval 函数.其中setTimeout 只能运行一次,只有在处理函数里面再嵌套一个setTimeout才能完成不断的调用,从而实现定时功能,这比较繁琐,还是用setInterval吧.下面是一个setInterval的代码例子:&l...
  • yuqixiansheng
  • yuqixiansheng
  • 2016-08-10 10:45
  • 2157

js中两种定时器,setTimeout和setInterval的区别

setTimeout只在指定时间后执行一次,代码如下: //定时器 异步运行 function hello(){ alert("hello"); } //使用方法名字执行方法 var t1 = window.setTimeout(hello,1000); var t2 = wi...
  • shenyanwei
  • shenyanwei
  • 2017-03-31 09:22
  • 1220

JavaScript定时器详解

定时器 来自《JavaScript 标准参考教程(alpha)》,by 阮一峰目录 setTimeout() setInterval() clearTimeout(),clearInterval() 运行机制 setTimeout(f,0) 含义 应用 正常任务与微任务 参考链接 Jav...
  • andyliulin
  • andyliulin
  • 2017-02-17 11:01
  • 407

深入理解javascript之高级定时器

setTimeout()和setInterval()可以用来创建定时器,其基本的用法这里就不再做介绍了。这里主要介绍一下javascript的代码队列。在javascript中没有任何代码是立即执行的,一旦进程空闲则尽快执行。所以说定时器中设置的时间并不代表执行时间就一定相符,而是代表代码会在指定时...
  • mevicky
  • mevicky
  • 2015-12-29 15:52
  • 2326

定时器Interval实现倒计时功能

功能: 做一个按钮“点击开始”,点击之后进入倒计时,倒计时完毕之后变回”点击开始“代码:<!DOCTYPE html> <html> <head> <meta charset="utf-8">...
  • Xanthin
  • Xanthin
  • 2015-12-21 20:06
  • 1226
    个人资料
    • 访问:391586次
    • 积分:5812
    • 等级:
    • 排名:第5288名
    • 原创:167篇
    • 转载:42篇
    • 译文:8篇
    • 评论:109条
    博客专栏
    最新评论
    spring学习之路
    开始重新学习spring了,记录自己的点点滴滴,加油吧,少年。