簡單談談setTimeout與setInterval

感謝踩過的坑

sf社區的第一篇文章。

最近在作一個拍賣的微信小程序,用到了定時器setTimout和setInterval,簡單談談這兩個api。前端


  • setTimeout

clipboard.png

最多見的用法就是第二種(第三種mdn文檔不推薦),如:es6

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清掉定時器。底層原理或許會有些不一樣,這裏就不深究。api


下面是我在微信小程序倒計時組件:微信

// components/countdown.js
/**
 * 倒計時組件
 */
Component({
  /**
   * 組件的屬性列表
   */
  properties: {
    durationInit: {
      type: Number,
      value: 0,
      observer: function(newVal) {  //監控duration初始值變更(看有沒有外部傳入新的時間)
        this.initDuration(newVal)
      }
    }
  },

  /**
   * 組件的初始數據
   */
  data: {
    duration: 0, //剩餘時間,單位秒
    timeDisplay: '' //展現時間
  },
  intervalId: null, //計時器Id,不須要渲染,放外面,省得影響性能

  /**
   * 組件銷燬了要清除計時
   */
  detached() {
    this.stopInterval(this.intervalId)
  },

  /**
   * 組件的方法列表
   */
  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(Math.floor(duration / 3600) % 24)
      var d = this.formatTime(Math.floor(duration / 3600 / 24))
      var time = `${d}:${h}:${m}:${s}`
      //寫入
      this.setData({
        timeDisplay: time
      })
      return true
    },
    //倒計時
    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),
          1000
        )

        this.intervalId = intervalId
      }
    },
    //初始化剩餘時間
    initDuration: function(newVal) {
      if (this.intervalId) {
        //如有計時器,清除
        this.stopInterval(this.intervalId)
      }
      this.setData({
        duration: this.data.durationInit
      })
      this.countDown(newVal)
    },
    //清除計時器
    stopInterval: function(intervalId) {
      if (intervalId != null) {
        clearInterval(intervalId)
        this.intervalId = null
      }
    },
    //格式化時間
    formatTime(time) {
      return time < 10 ? `0${time}` : `${time}`
    }
  }
})

最後想吐槽一下W3School,隨着學習的深刻,發現W3School的坑真多,強烈建議不要看W3School學前端,要看MDN文檔。可能不少人的前端啓蒙就是W3School,我也是。名字跟W3C很像,還覺得是很是專業的網站,然然後來發現跟W3C並無什麼關係。W3School在baidu搜索排名很是高,被坑了,baidu也是同謀。如今早已擁抱google,清爽!
下面就拿setInterval的說明作例子,對比一下MDN和W3School,就知道後者有多坑了。函數

clipboard.png

clipboard.png

clipboard.png

經過上面3張圖片,能夠看出
1. W3School含糊其辭,解釋不清楚,不詳細。用的時候容易出問題
W3School:週期性執行...請告訴我若是先執行了回調函數,再等待1秒,再執行回調函數,這算不算得上週期性??
MDN:詳細指出函數的每次調用會在該延遲以後發生性能

2. 不推薦的用法沒有指出,文檔更新慢,權威性極低
W3School:連舉的例子都是不推薦的用法,用code代碼串。。。
MDN:詳細指出使用code不推薦,不只如此,還發散性指出緣由和eval()同樣,真的很貼心很友好了學習


以上圖片均來源於MDN和W3School網站

在最後,感謝踩過的坑,讓我成長!初來乍到,多多關照,但願能堅持寫技術博文。

相關文章
相關標籤/搜索