zoukankan      html  css  js  c++  java
  • 使用setTimeout()代替setInterval()

    背景:

      在JavaScript中,有两种定时器:setTimeout()和setInterval();setTimeout()只执行一次定时操作,setInterval()执行无限次定时操作;但是大多数的观点均是尽可能多使用setTimeout(),多次定数操作也是十使用setTimeout()代替setInterval()。

    定时器的运行原理:

      要了解这样做原因首先要知道定时器的工作方式:JavaScript语言是单线程语言,它有一个叫做执行队列的东西来决定代码的执行顺序,而定时器的作用是:在特定的时间后将代码插入到执行队列。

      这里要特别理解:定时器setTimeout(function, Interval)这里的Interval是指当Interval个单位时间过去之后将代码function插入到执行队列中,而不是过去Interval个单位时间之后执行function代码。也就说明代码的执行的时间将大于等于Interval。

    setInterval()定时器存在的问题:

      1.  定时器中的某些间隔会被跳过;

      2.  定时器之间的代码间隔可能会比预期小;

      对于存在问题1的理解:如上图所示:这个例子中的第 1 个定时器是在 205ms 处添加到队列中的(即使任务队列为空,0ms实际上是达不到的,因此至少为5ms),但是直到过了 300ms 处才能够执行。当执行这个定时器代码时,在 405ms 处又给任务队列添加了另外一个副本。在下一个间隔,即 605ms 处,第一个定时器代码仍在运行,同时在任务队列中已经有了一个定时器代码的实例。结果是,在这个时间点上的定时器代码不会被添加到队列中。结果在 5ms 处添加的定时器代码结束之后,405ms 处添加的定时器代码就立刻执行。

      对于存在问题2的理解:某个 onclick 事件处理程序使用 setInterval() 设置了一个 200ms 间隔的重复定时器。如果事件处理程序花了 300ms 的时间完成,同时定时器代码也花了差不多的时间,就会同时出现跳过间隔且连续运行定时器代码的情况。

    个人疑惑之处:

      首先是对于setInterval的问题1,自己尝试了写演示代码,发现最后都不能得到自己想要的输出结果(最大可能是自己理解得不够深),因为不知道用什么方法捕获那个被跳过的代码。最后我发现了一个特点:其实定时器忽略某个插入代码,好像是无关紧要的,因为一般的我们插入的函数中都包含这一些操作函数,这些操作函数如果没有执行,那么参数就不会发生变化,那么就不会影响最后的输出结果。

      对于setInterval的问题2,自己写出了演示代码, 演示代码如下:

     1 const log = console.log.bind(console)
     2 
     3 const timeDelay = (delayTime) => {
     4     let time = new Date()
     5     // console.log(time.getTime())
     6     while(true) {
     7         var t1 = new Date()
     8         if ((t1.getTime() - time.getTime()) >= Number(delayTime)) {
     9             // console.log(t1.getTime())
    10             break
    11         }
    12     }
    13 }
    14 
    15 const func = () => {
    16     console.log("开始执行时间:" + new Date().toLocaleTimeString())
    17     timeDelay(6000)
    18     console.log("结束执行时间:" + new Date().toLocaleTimeString())
    19 }
    20 
    21 // console.log(new Date().toLocaleTimeString())
    22 
    23 // setInterval(func, 2000)
    24 // 开始执行时间:19:42:36
    25 // 结束执行时间:19:42:42
    26 // 开始执行时间:19:42:42 // 上一次的结束到下一次的开始, 间隔为0
    27 // 结束执行时间:19:42:48
    28 // 开始执行时间:19:42:50 // 上一次的结束到下一次的开始, 间隔为2(不太理解这里时间间隔为什么为2s)
    29 // 结束执行时间:19:42:56
    30 // 开始执行时间:19:42:56 // 上一次的结束到下一次的开始, 间隔为0
    31 
    32 
    33 setTimeout(function () {
    34     func()
    35     setTimeout(arguments.callee, 2000)
    36 },2000)
    37 // 开始执行时间:19:44:45
    38 // 结束执行时间:19:44:51
    39 // 开始执行时间:19:44:53 // 上一次的结束到下一次的开始, 间隔为2
    40 // 结束执行时间:19:44:59
    41 // 开始执行时间:19:45:01 // 上一次的结束到下一次的开始, 间隔为2
    42 // 结束执行时间:19:45:07
    43 // 开始执行时间:19:45:09 // 上一次的结束到下一次的开始, 间隔为2

    使用setTimeout代替setInterval的方法:

     1 let n = setTimeout(function () {
     2     // 判断是否将操作代码插入执行队列
     3     if (boolean) {
     4         // 需要插入执行队列的代码
     5         function()
     6     }
     7     // 判断是否进行定时器的递归
     8     if () {
     9         n = setTimeout(arguments.callee, interval)
    10     }
    11 }, interval)

      最好假如判断条件,这样方便控制整个定时器的循环

    引用:

      1. JavaScript定时器及相关面试题:https://www.cnblogs.com/unclekeith/p/6443115.html

      

      

  • 相关阅读:
    浅谈C#托管程序中的资源释放问题
    c#基本语法学习笔记
    深入剖析C#多态性
    Reporting Services API
    进程和线程的区别
    化妆品网站,饰品网站
    宠物销售网站
    卖地方特色才产品,类似湖南味道那样的网上专卖店
    建立友情链接联盟
    DIY最残忍U盘
  • 原文地址:https://www.cnblogs.com/oulae/p/11076432.html
Copyright © 2011-2022 走看看