关于JavaScript中的定时器(一)

2,426 阅读4分钟

前言

在开发过程中,我们总会遇到一些功能需要使用定时器来实现,我们常用的有:setInterval();setTimeout();clearInterval();clearTimeout()。今天让我们来仔细的研究一下吧~

1. setInterval()

setInterval()方法重复调用一个函数或执行一个代码段,在每次调用之间具有固定的时间延迟。通俗来讲即setInterval()方法内的函数片段会一直在固定的时间延迟后重复执行,直到清除本次重复操作的唯一辨识符intervalID。

语法

let intervalID = window.setInterval(func, delay[, param1, param2, ...]);

参数:

  • intervalID 是此重复操作的唯一辨识符,可以作为参数传给clearInterval()。
  • func 是你想要重复调用的函数。
  • delay 是每次延迟的毫秒数 (一秒等于1000毫秒),函数的每次调用会在该延迟之后发生。和setTimeout一样,实际的延迟时间可能会稍长一点。

常见应用:打字机效果, 计时器

一个小demo:

// 自动结束的计时器

var timesRun = 0;
var interval = setInterval(function(){
    timesRun += 1;
    if(timesRun === 60){    
        clearInterval(interval);    
    }
}, 1000);

2. setTimeout()

setTimeout()方法设置一个定时器,该定时器在定时器到期后执行一个函数或指定的一段代码。通俗来讲即setTimeout()在指定的毫秒数后调用函数或计算表达式。只执行一次,执行完毕后定时器就停止(定时器还在,但不再调用)。

语法

var timeoutID=scope. setTimeout(function, delay, paraml, param2,..]); 
var timeoutID=scope. setTimeout(function[, delay]); 

参数:

  • function 是你想要在到期时间(delay毫秒)之后执行的函数。
  • delay(可选) 延迟的毫秒数 (一秒等于1000毫秒),函数的调用会在该延迟之后发生。如果省略该参数,delay取默认值0,意味着“马上”执行,或者尽快执行。不管是哪种情况,实际的延迟时间可能会比期待的(delay毫秒数) 值长,主要是因为(1)setTimeout在浏览器中有一个最小约定值(4ms-10ms);(2)浏览器在执行过程中会先执行主线程代码,待主线程代码运行完毕后才会再执行setTimeout()
  • param1, ..., paramN(可选) 附加参数,一旦定时器到期,它们会作为参数传递给function

返回值

返回值timeoutID是一个正整数,表示定时器的编号。这个值可以传递给clearTimeout()来取消该定时器。

常见应用:

  • 在vue中想要页面加载后获取ref元素时,可以将要获取的元素代码写入setTimeout(() => {}, 0),或者使用vue官方给出的
this.$nextTick(() => {
    this.msg2 = this.$refs.msgDiv.innerHTML
})
  • 等待几秒后执行的操作
  • 倒计时(demo如下)
<html>
    <head>
        <script>
            x = 60
            function countSecond(){
                x --
                document.fm.displayBox.value=x
                setTimeout("countSecond()", 1000)
            }
        </script>
    </head>
    <body bgcolor=lightcyan text=red><p></br>
        <form name=fm>
            <input type="text" name="displayBox"value="0" size=4 >
        </form>
        <script>
            countSecond()
        </script>
    </body>
</html>

3. clearInterval() 和 clearTimeout()

取消setInterval或setTimeout设置的重复定时任务。setTimeout()和setInterval()共用一个编号池,技术上,clearTimeout()和 clearInterval() 可以互换。但是,为了避免混淆,不要混用取消定时函数。

语法

window.clearInterval(intervalID)
window.clearTimeout(timeoutID)

demo:在一个网页中运行如下脚本,并且点击一次页面。一秒钟后你会看见弹出一条信息。如果你在一秒内不停点击页面,弹出框将不再出现。

var alarm = {
  remind: function(aMessage) {
    alert(aMessage);
    delete this.timeoutID;
  },

  setup: function() {
    this.cancel();
    var self = this;
    this.timeoutID = window.setTimeout(function(msg) {self.remind(msg);}, 1000, "Wake up!");
  },

  cancel: function() {
    if(typeof this.timeoutID == "number") {
      window.clearTimeout(this.timeoutID);
      delete this.timeoutID;
    }
  }
};
window.onclick = function() { alarm.setup() };

注意: 传入一个错误的 ID 给 clearTimeout()或clearInterval()不会有任何影响;也不会抛出异常

setInterval() 和 setTimeout()的区别

setTimeout():只执行一次; setInterval():重复执行直到手动暂停或窗关闭。

setInterval的弊端和解决方案

弊端

  1. setInterval对自己调用的代码是否报错漠不关心。即使调用的代码报错了,它依然会持续的调用下去
  2. setInterval无视网络延迟。在使用ajax轮询服务器是否有新数据时,必定会有一些人会使用setInterval,然而无论网络状况如何,它都会去一遍又一遍的发送请求,如果网络状况不良,一个请求发出,还没有返回结果,它会坚持不懈的继续发送请求,最后导致的结果就是请求堆积。
  3. setInterval并不定时。如果它调用的代码执行的时间小于定时的时间,它会跳过调用,这就导致无法按照你需要的执行次数或无法得到你想要的结果。

解决方法

使用setTimeout代替setInterval。可以给setTimeout设置时间后,在最后调用自身。如果希望“匀速”触发。可以计算代码执行时间,用希望的延迟减去上次执行的时间。