zoukankan      html  css  js  c++  java
  • 谈谈javascript中的定时器

    最近写一些JS动画,常用到JS中的定时器(setTimeout & set Interval),查找相关资料,有些心得与大家一起分享。

    使用setTimeout & set Interval创建的定时器可以实现有趣且有用的功能,初学者可能对Javascript的定时器有误解,认为它们是线程,其实Javascript是运行于单线程中的,而定时器仅仅是计划在未来的某个时间执行,而具体的执行时间是不能保证的,因为在页面的生命周期中,不同的时间可能有其它代码在控制Javascript的里进程。浏览器只是负责进行排序,指派某个代码在某个时间点运行。

    下面说下Javascript线程,下图表示javascript进程时间线。

    image

    除了javascript执行进程外,还有一个需要在进程下一次空闲时间执行的代码队列,随着页面在其生命周期内的推移,代码会按照执行顺序添加到对列中,例如:当一个按钮被按下时,它的事件处理就会添加到队列中,并在下一个可能的时间内执行。

    定时器对队列的工作方式是,当特定的时间过去后,将代码插入,注意添加到队列并不意味着它会马上执行,而只能说它会尽快执行,设定一个250ms后执行的定时器,不代表250ms后它会马上执行,它只会表示在150ms后被加入到队列中,如果这个时间点队列是空闲的,那么这段代码就会被执行。

    请看以下代码:

    var btn = document.getElementById("mybtn");
        btn.onclick = function () {
            setTimeout(function () {
                document.getElementById("message").nodeName = "mymessage";
                //其它代码
            }, 250);
        }

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

    image

    setTimeout() :未来的某时执行代码 ;clearTimeout() :取消setTimeout()。
    下面展示一个简单的计时,并带有停止功能:
    <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>
    
    <input type="button" value="开始计时!" onClick="timedCount()">
    <input type="text" id="txt">
    <input type="button" value="停止计时!" onClick="stopCount()">
     

    setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。

    setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。

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

    为避免这些问题,可以使用如下模式使用链式setTimeout调用:

    setTimeout(function () {
            //处理中
            setTimeout(arguments.callee, interval);
        }, interval)

    在上面的计时DEMO中也是使用此模式来做循环的。

  • 相关阅读:
    redis使用lua脚本遇到的问题
    redis使用scan count 返回数量不准确
    window系统下搭建本地的NuGet Server
    windows10使用docker发布.netcore程序
    windows10使用docker安装mysql
    windows10搭建redis4.0集群
    windows10配置redis主从复制
    windows10安装redis4.0
    mysql 共享排他锁
    mysql drop表以后恢复数据
  • 原文地址:https://www.cnblogs.com/Wenwang/p/2314283.html
Copyright © 2011-2022 走看看