js定时器

232 阅读1分钟

计数器

刷新继续倒计时

时间校准

添加每次计数的触发函数

结束的触发函数

链式调用

中途停止,不计入总时间

class Clock {
  constructor(time, id = "Clock") {
    this.id = id; // 计时器id,用来取结束时间和暂停时间
    this.count = time;
    this.fnCallBacks = []; // 每次计时的回调函数
    this.end = () => {
      // 计时结束的响应函数
      console.log("结束了");
    };
    this.stopTime = null; //停止的时间戳
    this.lastTime = null; //上次的时间戳
    this.setTimeNo = null; //下一次的 settimeout 的 id
    this.default = {
      count: time,
      stopTime: null,
      stopTime: null,
      lastTime: null,
      setTimeNo: null
    };
  }
  /**
   * 启动函数
   */
  run() {
    this.startTime = Number(new Date());
    this.stopTime =
      this.stopTime || sessionStorage.getItem(`${this.id}_stopTime`); //停止的时间
    let cache = Number(sessionStorage.getItem(this.id)); //获得缓存的结束时间
    if (this.stopTime) {
      cache = this.startTime - Number(this.stopTime) + cache;
      sessionStorage.setItem(this.id, cache); //更新结束时间
      this.stopTime = null; //移除计时器
      sessionStorage.removeItem(`${this.id}_stopTime`); //移除计时器
    }

    const start = () => {
      setTimeout(() => {
        this.start();
      }, 0);
    };
    if (cache) {
      //如果有缓存的话
      const time = cache - Number(new Date()); //距离结束时间打大小
      if (time <= 0) {
        //已经超时了
        sessionStorage.removeItem(this.id); //移除计时器
        sessionStorage.removeItem(`${this.id}_stopTime`); //移除计时器
        this.end();
      } else {
        //计算count,定时器继续跑
        this.count = Math.ceil(time / 1000);
        start();
      }
    } else {
      sessionStorage.setItem(
        this.id,
        Number(this.startTime) + this.count * 1000
      ); //存储结束时间
      start();
    }

    return this;
  }
  /**
   * 轮询的主函数
   */
  start() {
    for (let fn of this.fnCallBacks) {
      fn(this.count);
    }
    const currentTime = Number(new Date()); // 校准变量
    //1000-(currentTime-lastTime-1000) =2000-currentTime+this.lastTime
    let time;
    if (this.lastTime) {
      time = 2000 - currentTime + this.lastTime; // 校准变量
    } else {
      time = 1000;
    }
    console.log("校准", time.valueOf(), this.count);
    this.count--;
    this.setTimeNo = setTimeout(() => {
      this.lastTime = currentTime;
      if (this.count > -1) {
        this.start();
      } else {
        this.end();
        sessionStorage.removeItem(this.id); //移除计时器
        sessionStorage.removeItem(`${this.id}_stopTime`); //移除计时器
        console.log("总共耗时", new Date() - this.startTime);
      }
    }, time);
    return this;
  }
  /**
   *
   * @param {function} fn
   */
  pushFn(fn) {
    this.fnCallBacks.push(fn);
    return this;
  }
  /**
   * 终止函数
   * @param {number} time
   */
  stop(time = 0) {
    setTimeout(() => {
      clearTimeout(this.setTimeNo);
    }, time);
    console.log("总共耗时", new Date() - this.startTime);
    this.lastTime = null; //校准归零
    this.stopTime = Number(new Date());
    sessionStorage.setItem(`${this.id}_stopTime`, this.stopTime);
    return this;
  }
  /**
   * 初始化函数
   */
  init() {
    clearTimeout(this.setTimeNo);
    sessionStorage.removeItem(this.id); //移除计时器
    sessionStorage.removeItem(`${this.id}_stopTime`); //移除计时器
    for (let i in this.default) {
      this[i] = this.default[i];
    }
    return this;
  }
  /**
   * 设置结束回调
   * @param {function} fn
   */
  setEnd(fn) {
    this.end = fn;
    return this;
  }
}
var demo = new Clock(60, "test", e => {
  console.log(e);
}).run();