yoowinsu / blog

issues blog
17 stars 3 forks source link

记一次setTimeout的坑 #68

Open yoowinsu opened 6 years ago

yoowinsu commented 6 years ago

下面代码是toast组件中的一段代码,setTimeout两秒后消失,

        let startTime = new Date();
        if (toast.show) {
          toast.timeout = setTimeout(() => {
            toast.show = false;
            console.log(new Date() - startTime);
            clearTimeout(toast.timeout);
          }, 1000);
        }

在页面没有其他定时函数的时候,console打印的事件间隔差不多都是1秒左右, 如下图:

2018-03-15_152244

但是页面有倒计时的情况下,toast组件的消失时间越来越长,如下图: image

倒计时的函数是这样写的:

    countdownTime (endTime) {
      const nowTime = new Date().getTime() / 1000;
      this.leftTime = parseInt(endTime - nowTime);
      let that = this;
      that.timeout0 = setInterval(function () {
        if (that.leftTime > 0) {
          that.leftTime--;
        } else {
          clearInterval(that.timeout0);
        }
      }, 1000);
      let d = Math.floor(that.leftTime / (60 * 60 * 24));
      let h = parseInt(that.leftTime / (60 * 60)) % 24;
      let m = parseInt(that.leftTime / 60 % 60);
      let s = parseInt(that.leftTime % 60);
      if (d) {
        return `${d}天${h}小时${m}分${s}秒`;
      } else {
        return `${h}小时${m}分${s}秒`;
      }
    }

排查之后发现,setInterval函数应该在每次leftTime值改变后清除一下,改变代码后:

    countdownTime (startTime, endTime) {
      const nowTime = new Date().getTime() / 1000;
      this.leftTime = parseInt(endTime - nowTime);
      let that = this;
      that.timeout0 = setInterval(function () {
        if (that.leftTime > 0) {
          that.leftTime--;
          clearInterval(that.timeout0);
        } else {
          clearInterval(that.timeout0);
        }
      }, 1000);
      let d = Math.floor(that.leftTime / (60 * 60 * 24));
      let h = parseInt(that.leftTime / (60 * 60)) % 24;
      let m = parseInt(that.leftTime / 60 % 60);
      let s = parseInt(that.leftTime % 60);
      if (d) {
        return `${d}天${h}小时${m}分${s}秒`;
      } else {
        return `${h}小时${m}分${s}秒`;
      }
    }

改了之后就正常了,这次一个教训就是,凡是用到setIntervalsetTimeout的地方,一定要清楚定时器!