微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

简单谈谈setTimeout与setInterval

感谢踩过的坑

sf社区的第一篇文章

最近在做一个拍卖的微信小程序,用到了定时器setTimout和setInterval,简单谈谈这两个api。


  • setTimeout

最常见的用法就是第二种(第三种mdn文档不推荐),如:

var timeoutId = setTimeout(function() {
    console.log('Hello World!')
},1000)

定时器是先等待1000ms再执行function的语句,而不是一开始就执行然后再等待。如果执行的语句需要用到this引用,需要在回调函数function上绑定this:function() {...}.bind(this),把this传给回调函数,同作为该回调函数的this,使回调函数内外this的指向保持一致。或者用es6的箭头函数() => {},也能起到同样的作用。bind的用法详见Function.prototype.bind()

用完定时器之后,要记得清除clearTimeout(timeoutId) 这里的timeoutId是setTimeout返回的一个正整数编号,是定时器的唯一标识符。


  • setInterval
  • 在我看来基本上可以当成setTimeout的升级版,就像setTimeout循环调用自身,用法也跟setTimeout一样,用完是也要记得用clearInterval清掉定时器。底层原理或许会有些不同,这里就不深究。


    下面是我在微信小程序倒计时组件:

    // components/countdown.js
    /**
     * 倒计时组件
     */
    Component({
      /**
       * 组件的属性列表
       */
      properties: {
        durationInit: {
          type: Number,value: 0,observer: function(newVal) {  //监控duration初始值变动(看有没有外部传入新的时间)
            this.initDuration(newVal)
          }
        }
      },/**
       * 组件的初始数据
       */
      data: {
        duration: //剩余时间,单位秒
        timedisplay: '' //展示时间
      },intervalId: null,136);">//计时器Id,不需要渲染,放外面,免得影响性能
    
      /**
       * 组件销毁了要清除计时
       */
      detached() {
        this.stopInterval(this.intervalId)
      },136);">/**
       * 组件的方法列表
       */
      methods: {
        // 设置时间
        setTime: function(duration) {
          if (duration <= 0) {
            this.setData({
              timedisplay: `活动结束啦`
            })
            //this.data.timedisplay = `活动结束啦,戳这里看看好东西~`
            return false
          }
          var s = this.formatTime(duration % 60)
          var m = this.formatTime(Math.floor(duration / 60) % 60)
          var h = this.formatTime(3600) % 24)
          var d = this.formatTime(3600 / 24))
          var time = `${d}:${h}:${m}:${s}`
          //写入
          this.setData({
            timedisplay: time
          })
          return true
        },136);">//倒计时
        countDown: function(duration) {
          //有没有倒计时的必要.第一次展示时间(这个很重要)
          var canCountDown = this.setTime(duration)
    
          if (canCountDown === true) {
            var intervalId = setInterval(
              function() {
                //清除计时器
                if (this.data.duration <= 0) {
                  this.stopInterval(intervalId)
                }
                this.setData({
                  duration: this.data.duration - 1
                })
    
                this.setTime(this.data.duration)
              }.bind(this),128);">1000
            )
    
            this.intervalId = intervalId
          }
        },136);">//初始化剩余时间
        initDuration: function(newVal) {
          if (this.intervalId) {
            //若有计时器,清除
            this.stopInterval(this.intervalId)
          }
          this.setData({
            duration: this.data.durationInit
          })
          this.countDown(newVal)
        },136);">//清除计时器
        stopInterval: function(intervalId) {
          if (intervalId != null) {
            clearInterval(intervalId)
            this.intervalId = null
          }
        },136);">//格式化时间
        formatTime(time) {
          return time < 10 ? `0${time}` : ${time}`
        }
      }
    })
    

    最后想吐槽一下W3School,随着学习的深入,发现W3School的坑真多,强烈建议不要看W3School学前端,要看MDN文档。可能很多人的前端启蒙就是W3School,我也是。名字跟W3C很像,还以为是非常专业的网站,然而后来发现跟W3C并没有什么关系。W3School在baidu搜索排名非常高,被坑了,baidu也是同谋。现在早已拥抱google,清爽!
    下面就拿setInterval的说明做例子,对比一下MDN和W3School,就知道后者有多坑了。

    通过上面3张图片,可以看出
    1. W3School含糊其辞,解释不清楚,不详细。用的时候容易出问题
    W3School:周期性执行...请告诉我如果先执行了回调函数,再等待1秒,再执行回调函数,这算不算得上周期性??
    MDN:详细指出函数的每次调用会在该延迟之后发生

    2. 不推荐的用法没有指出,文档更新慢,权威性极低
    W3School:连举的例子都是不推荐的用法,用code代码串。。。
    MDN:详细指出使用code不推荐,不仅如此,还发散性指出原因和eval()一样,真的很贴心很友好了


    以上图片均来源于MDN和W3School

    在最后,感谢踩过的坑,让我成长!初来乍到,多多关照,希望能坚持写技术博文。

    版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。