Source: tiny/core/ticker/CountDown.js

import EventEmitter from 'eventemitter3';
import * as utils from '../utils';
import { arrayRemoveObject, getTime } from '../../../utils';
import Ticker from './Ticker';

const MANUAL_STOP = 'manual stop';
const MANUAL_PAUSE = 'manual pause';

/**
 * 一个高精度、高性能的计时器
 *
 * @example
 * var cd1 = new Tiny.ticker.CountDown({
 *   duration: 5e3,
 *   times: 3,
 * });
 * cd1.on('update', function (t) {
 *   console.log('每五秒打印一次,共打印三次');
 * });
 * cd1.on('complete', function (t) {
 *   console.log('Done');
 * });
 * cd1.start();
 *
 * @example
 * var cd2 = new Tiny.ticker.CountDown({
 *   duration: 3e3,
 * });
 * cd2.on('update', function (t) {
 *   console.log('每三秒打印一次,第' + cd2.count + '次');
 * });
 * cd2.start();
 *
 * @version 1.1.7
 * @class
 * @memberof Tiny.ticker
 */
export default class CountDown extends EventEmitter {
  /**
   * @param {number} opts.duration - 每次的时间间隔(ms)
   * @param {number} opts.times - 共计次数
   */
  constructor(opts) {
    super();

    /**
     *
     * @member {number}
     * @default 1000ms
     */
    this.duration = opts.duration || 1e3;

    /**
     *
     * @member {number}
     * @default Infinity
     */
    this.times = opts.times || Infinity;

    /**
     * 已计次数
     *
     * @member {number}
     * @default 0
     */
    this.count = 0;

    utils.CountDownCache.push(this);

    /**
     * 每间隔 `duration` 触发一次
     *
     * @example
     * var cd = new Tiny.ticker.CountDown();
     * cd.on('update', function(){
     *   console.log('tick');
     * });
     *
     * @event Tiny.ticker.CountDown#update
     * @param {number} time
     */

    /**
     * 如果传入 `times`,则会在计时结束后触发
     *
     * @event Tiny.ticker.CountDown#complete
     * @param {number} time
     */

    /**
     * 调用 `CountDown.pause()` 后触发
     *
     * @example
     * var cd = new Tiny.ticker.CountDown();
     * cd.on('pause', function(){
     *   console.log('paused');
     * });
     * cd.pause();
     *
     * @event Tiny.ticker.CountDown#pause
     */

    /**
     * 调用 `CountDown.stop()` 后触发
     *
     * @example
     * var cd = new Tiny.ticker.CountDown();
     * cd.on('stop', function(){
     *   console.log('stop');
     * });
     * cd.stop();
     *
     * @event Tiny.ticker.CountDown#stop
     */
  }

  /**
   * 开始计时,如果是被暂停的计时器,会从上次暂停点继续
   */
  start() {
    this._indicate = null;
    if (this.count >= this.times) {
      return;
    }
    /**
     * 计时器使用的 Ticker 对象
     * @member {Tiny.ticker.Ticker}
     */
    this.ticker = new Ticker();
    this.startTime = getTime();

    const tickerHandler = (time) => {
      const current = getTime();
      if (this.count >= this.times) {
        this.ticker.destroy();

        this.emit('complete', time);
        return;
      }
      if (current - this.startTime >= this.duration) {
        this.startTime = current;
        this.count++;
        this.emit('update', time);
      }
    };
    this.ticker.add(tickerHandler);
    this.ticker.start();
  }

  /**
   * 暂停计时,再次执行 `start` 会从上次暂停点继续
   */
  pause(auto) {
    this.ticker.destroy();
    if (!auto) {
      this._indicate = MANUAL_PAUSE;
    }
    this.emit('pause');
  }

  /**
   * 停止计时
   */
  stop(auto) {
    this.ticker.destroy();
    this.count = 0;
    if (!auto) {
      this._indicate = MANUAL_STOP;
    }
    this.emit('stop');
  }

  // 是否手动暂停
  isManualPause() {
    return this._indicate === MANUAL_PAUSE;
  }

  // 是否手动停止
  ifManualStop() {
    return this._indicate === MANUAL_STOP;
  }

  /**
   * 销毁计时器
   */
  destroy() {
    this.stop();
    arrayRemoveObject(utils.CountDownCache, this);
  }

  /**
   * 计时器是否正在运行
   *
   * @return {boolean}
   * @default false
   * @readonly
   */
  get running() {
    return this.ticker.started;
  }
}
Documentation generated by JSDoc 3.4.3 on Fri Jul 09 2021 19:32:25 GMT+0800 (CST)