zoukankan      html  css  js  c++  java
  • js函数——setinterval和setTimeout

    1.window.setTimeout方法

    该方法可以延时执行一个函数,例如:

    <script language="JavaScript" type="text/javascript">

    <!--

    function hello(){

    alert("hello");

    }

    window.setTimeout(hello,5000);

    //-->

    </script>

    这段代码将使得页面打开5秒钟后显示对话框“hello”。其中最后一句也可以写为:

    window.setTimeout("hello()",5000);

    如果在延时期限到达之前取消延执行,可以使用window.clearTimeout(timeoutId)方法,该方法接收一个id,表示一个定时器。这个id是由setTimeout方法返回的,例如:

    <script language="JavaScript" type="text/javascript">

    <!--

    function hello(){

          alert("hello");

    }

    var id=window.setTimeout(hello,5000);

    document.onclick=function(){

         window.clearTimeout(id);

    }

    //-->

    </script>

    这样,如果要取消显示,只需单击页面任何一部分,就执行了window.clearTimeout方法,使得超时操作被取消。

    2.window.setInterval方法

    该方法使得一个函数每隔固定时间被调用一次,是一个很常用的方法。如果想要取消定时执行,和clearTimeout方法类似,可以调用window.clearInterval方法。clearInterval方法同样接收一个setInterval方法返回的值作为参数。例如:

    //定义一个反复执行的调用

    var id=window.setInterval("somefunction",10000);

    //取消定时执行

    window.clearInterval(id);

    上面的代码仅用于说明怎样取消一个定时执行。实际上在很多场合都需要用到setInterval方法,下面将设计一个秒表,来介绍setInterval函数的用途:该秒表将包括两个按钮和一个用于显示时间的文本框。当单击开始按钮时开始计时,最小单位为0.01秒,此时再次单击按钮则停止计时,文本框显示经过的时间。另外一个按钮用于将当前时间清零。其实现代码如下:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

    <html>

    <head>

    <title> New Document </title>

    </head>

    <body>

    <form action="somepage.asp">

    <input type="text" value="0" name="txt1"/>

    <input type="button" value="开始" name="btnStart"/>

    <input type="button" value="重置" name="btnReset"/>

    </form>

    </body>

    </html>

    <script language="JavaScript" type="text/javascript">

    <!--

    //获取表单中的表单域

    var txt=document.forms[0].elements["txt1"];

    var btnStart=document.forms[0].elements["btnStart"];

    var btnReset=document.forms[0].elements["btnReset"]

    //定义定时器的id

    var id;

    //每10毫秒该值增加1

    var seed=0;

    btnStart.onclick=function(){

          //根据按钮文本来判断当前操作

          if(this.value=="开始"){

                  //使按钮文本变为停止

                  this.value="停止";

                  //使重置按钮不可用

                  btnReset.disabled=true;

                  //设置定时器,每0.01s跳一次

                  id=window.setInterval(tip,10);

          }else{

                  //使按钮文本变为开始

                  this.value="开始";

                  //使重置按钮可用

                  btnReset.disabled=false;

                  //取消定时

                  window.clearInterval(id);

          }

    }

    //重置按钮

    btnReset.onclick=function(){

         seed=0;

    }

    //让秒表跳一格

    function tip(){

          seed++;

          txt.value=seed/100;

    }

    //-->

    </script>

    3 给定时器调用传递参数

    无论是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)来返回一个不带参数的函数句柄,从而实现了参数传递的功能。

    4、二者区别

    setTimeout和setInterval这两个函数, 大家肯定都不陌生, 但可能并不是每个用过这两个方法的同学, 都了解其内部的实质,甚至可能会错误的把两个实现定时调用的函数理解成了类似thread一样的东西, 认为会在一个时间片内, 并发的执行调用的函数, 似乎很好很强大, 但其实并不是如此, 实际的情况是javascript都是以单线程的方式运行于浏览器的javascript引擎中的, setTimeout和setInterval的作用只是把你要执行的代码在你设定的一个时间点插入js引擎维护的一个代码队列中, 插入代码队列并不意味着你的代码就会立马执行的,理解这一点很重要. 而且setTimeout和setInterval还有点不一样. 

    先谈谈setTimeout 
    1. function click() {   
    2. // code block1...   
    3. setTimeout(function() {   
    4. // process ...   
    5. }, 200);   
    6. // code block2   
    7. }   
    假设我们给一个button的onclick事件绑定了此方法, 当我们按下按钮后, 肯定先执行block1的内容, 然后运行到setTimeout的地方, setTimeout会告诉浏览器说, "200ms后我会插一段要执行的代码给你的队列中", 浏览器当然答应了(注意插入代码并不意味着立马执行), setTimeout代码运行后, 紧跟其后的block2代码开始执行, 这里就开始说明问题了, 如果block2的代码执行时间超过200ms, 那结果会是如何? 或许按照你之前的理解, 会理所当然的认为200ms一到, 你的process代码会立马执行...事实是, 在block2执行过程中(执行了200ms后)process代码被插入代码队列, 但一直要等click方法执行结束, 才会执行process代码段, 从代码队列上看process代码是在click后面的, 再加上js以单线程方式执行, 所以应该不难理解. 如果是另一种情况, block2代码执行的时间<200ms, setTimeout在200ms后将process代码插入到代码队列, 而那时执行线程可能已经处于空闲状态了(idle), 那结果就是200ms后, process代码插入队列就立马执行了, 就让你感觉200ms后, 就执行了. 

    再看看setInterval 
    这里可能会存在两个问题: 
    1.时间间隔或许会跳过 
    2.时间间隔可能<定时调用的代码的执行时间 
    1. function click() {   
    2. // code block1...   
    3. setInterval(function() {   
    4. // process ...   
    5. }, 200);   
    6. // code block2   
    7. }   

    和上面一样我们假设通过一个click, 触发了setInterval以实现每隔一个时间段执行process代码

    比如onclick要300ms执行完, block1代码执行完, 在5ms时执行setInterval, 以此为一个时间点, 在205ms时插入process代码, click代码顺利结束, process代码开始执行(相当于图中的timer code), 然而process代码也执行了一个比较长的时间, 超过了接下来一个插入时间点405ms, 这样代码队列后又插入了一份process代码, process继续执行着, 而且超过了605ms这个插入时间点, 下面问题来, 可能你还会认为代码队列后面又会继续插入一份process代码...真实的情况是,由于代码队列中已经有了一份未执行的process代码, 所以605ms这个插入时间点将会
    被"无情"的跳过, 因为js引擎只允许有一份未执行的process代码, 说到这里不知道您是不是会豁然开朗呢...

    为了这种情况你可以用一种更好的代码形式

    1. setTimeout(function(){   
    2. //processing   
    3. setTimeout(arguments.callee, interval);   
    4. }, interval);   

    转自: http://blog.csdn.net/cui_angel/article/details/7768241

     
  • 相关阅读:
    idea 找不到包或找不到符号
    JOISC部分题解
    欧拉数学习笔记
    [清华集训2017]生成树计数
    [ZJOI2019]开关
    【题解】CF817E Choosing The Commander
    CSP-S 2020游记
    【学习笔记】线段树合并
    【题解】[IOI2005]Riv 河流
    【题解】哈希冲突
  • 原文地址:https://www.cnblogs.com/linguoguo/p/4181203.html
Copyright © 2011-2022 走看看