• JS之BOM篇setTimeout和setInterval


    setTimeout()

    setTimeout()方法用来指定函数或字符串在指定的毫秒数之后运行。它返回一个整数,表示定时器的编号,这个值可以传递给clearTimeout()方法用于取消对setTimeout的引用

    var timer = setTimeout(function(){
      console.log(timer)
    }, 1000)
    console.log(0)
    // 0
    // 1
    

    示例中,控制台先输出0,大概过1000ms后,输出定时器setTimeout()方法的返回值1

    第一个参数也可以写成字符串参数的形式,由于这种形式会造成javascript引擎两次解析,降低性能,故不建议使用

    var timer = setTimeout('console.log(timer);',1000);
    console.log(0);
    

    如果省略setTimeout的第二个参数,则该参数默认为0

    var timer = setTimeout(function(){
      console.log(timer)
    })
    console.log(0)
    // 0
    // 1
    

    除了前两个参数,setTimeout()方法还允许添加更多的参数,它们将被传入定时器中的函数中。

    注意: IE9-浏览器只允许setTimeout有两个参数

    setTimeout(function(a,b){
      console.log(a+b);
    },1000,1,1);
    
    // 2
    

    如果需要兼容IE9-,可以将函数写在定时器外面,然后函数在定时器中的匿名函数中带参数调用

    function test(a,b){
      console.log(a+b);
    }
    setTimeout(function(){
      test(1,1);
    },1000);
    

    clearTimeout()

    setTimeout函数返回一个表示计数器编号的整数值,将该整数传入clearTimeout函数,取消对应的定时器

    var timer = setTimeout(function(){
        console.log(timer);
    },100);
    // 清除定时器
    clearTimeout(1); 
    
    var timer = setTimeout(function(){
        console.log(timer);
    },100);
    // 清除定时器
    clearTimeout(timer); 
    

    上面两种清除定时器的方式效果是一样的,第二种更常用一些

    一般来说,setTimeout返回的整数值是连续的,也就是说,第二个setTimeout方法返回的整数值比第一个的整数值大1

    var timer1 = setTimeout(function(){
      console.log(timer1);
    },100);
    var timer2 = setTimeout(function(){
      console.log(timer2);
    },100);
    var timer3 = setTimeout(function(){
      console.log(timer3);
    },100);
    // 1
    // 2
    // 3
    

    setInterval()

    setInterval的用法与setTimeout完全一致,区别仅仅在于setInterval指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行。清除setInterval可以使用clearInterval()方法

    <button id="btn">0</button>
    <script>
    var timer = setInterval(function(){
      btn.innerHTML = Number(btn.innerHTML) + 1;
    },1000);
    
    btn.onclick = function(){
      clearInterval(timer);
      btn.innerHTML = 0;
    }
    </script>
    

    注意: HTML5标准规定,setTimeout的最短时间间隔是4毫秒;setInterval的最短间隔时间是10毫秒,也就是说,小于10毫秒的时间间隔会被调整到10毫秒

    大多数电脑显示器的刷新频率是60HZ,大概相当于每秒钟重绘60次。因此,最平滑的动画效的最佳循环间隔是1000ms/60,约等于16.6ms

    运行机制

    setTimeout(function(){
      console.log(1);
    });
    console.log(0);
    // 0
    // 1
    

    这个示例先打印了0,然后是1。这是因为当把setTimeout的第二个参数设置为0时,表示的不是立即调用的意思,它只是把函数放到异步队列中。浏览器要先执行同步队列里的任务,然后执行异步队列中的任务

    btn.onclick = function(){
      setTimeout(function(){
        console.log(1);
      },250);
    }
    

    这个示例中,点击btn按钮后发生了什么?简单来说发生了三件事:首先是将onclick事件处理程序加入队列等待执行;然后等到事件处理程序开始执行后,设置一个定时器;最后等250ms后,指定的代码才被添加到队列中等待执行,也就是console.log(1)

    如果用一张图表示一下,就是下面这样

    现在问题来了,事件处理程序执行了300ms,定时器在255ms处被添加到队列中,但是却不能执行,因为onclick事件处理程序还在运行中。因此定时器代码最早能执行的时机是在300ms处,即onclick事件处理程序结束之后

    setInterval()的问题

    setInterval()也有同样的问题,假设,某个onclick事件处理程序使用setInterval()设置了200ms间隔的定时器。如果事件处理程序花了300ms多一点时间完成,同时定时器代码也花了差不多的时间,就会同时出现跳过某间隔的情况

    示例中,第一个定时器是在205ms处添加到队列中的,但是直到过了300ms处才能执行。当执行这个定时器代码时,在405ms处又给队列添加了另一个副本。在下一个间隔,即605ms处,第一个定时器代码仍在运行,同时在队列中已经有了一个定时器代码的实例。结果是,在这个时间点上的定时器代码不会被添加到队列中

    迭代setTimeout

    setTimeout(function fn(){
      // do
      setTimeout(fn, interval)
    },interval)
    

    使用链式setTimeout()调用,可以避免setInterval()定时器的问题。在前一个定时器代码执行完之前,不会向队列插入新的定时器代码,确保不会有任何缺失的间隔。而且,它可以保证在下一次定时器代码执行之前,至少要等待指定的间隔,避免了连续的运行

    <div id="box" style=" 100px;height:100px;background: teal;position: absolute;left: 0;"></div>
    <script>
      box.onclick = function() {
        setTimeout(function fn(){
          if(parseInt(box.style.left) <= 200) {
            box.style.left = parseInt(box.style.left) + 5 + 'px';
            setTimeout(fn, 17)
          }else{
            return false;
          }
        }, 17)
      }
    </script>
    

    应用

    使用定时器可以调整事件发生的顺序

    应用一

    在网页开发中,由于事件冒泡的机制,子元素的事件回调函数会早于父元素的事件回调函数触发。如果希望父元素的事件回调函数先发生,就要用到setTimeout(fn, 0)

    <div id="box" style="height: 100px; 100px;background-color: pink;"></div>
    <script>
    box.onclick = function(){
      setTimeout(function(){
        alert(0);
      })
    }
    document.onclick = function(){
      alert(1);
    }
    </script>
    

    示例中,点击box盒子会先弹出1,然后弹出0

    应用二

    通常由用户触发的回调函数,会在浏览器的默认动作之前触发。比如用户在input中输入文本,keypress事件会在浏览器接受到文本前触发

    <input type="text" id="myInput">
    <script>
    myInput.onkeypress = function(event) {
      this.value = this.value.toUpperCase();
    }
    </script>
    

    这个示例的用意是想把用户输入的字符自动转换成大写,但是由于keypress事件会在浏览器接收文本之前触发,因此只能把前一个字符转换成大写。使用setTimeout可以轻松解决这个问题

    <input type="text" id="myInput">
    <script>
    myInput.onkeypress = function(event) {
      setTimeout(function(){
        myInput.value = myInput.value.toUpperCase();
      })
    }
    </script>
    
    优秀文章首发于聚享小站,欢迎关注!
  • 相关阅读:
    mysql一个字段多个值如何分别取出这些值
    mysql json数组取值、查询
    mui删除元素
    软件测试的艺术(读书笔记1)
    爬虫(3)_网站分析
    谈谈作为测试的8年
    测试有前景吗?
    爬虫(二)-创建项目&应用
    爬虫(一)-环境搭建
    puppeteer UI自动化测试demo(一)
  • 原文地址:https://www.cnblogs.com/yesyes/p/15352573.html
Copyright © 2020-2023  润新知