美文网首页
[TypeScript] 基于本地时间的定时器

[TypeScript] 基于本地时间的定时器

作者: 码上说 | 来源:发表于2020-05-01 00:03 被阅读0次
计时器

点击获取源码

API

  • constructor : 构造器
  /**
   * 定时器构造器
   * @summary 构造时使用秒为单位,实际会转换成毫秒
   * @param callback 定时器回调
   * @param call_interval 定时器调用间隔
   * @param stop_after 停止时间
   * @param call_after 延迟时间
   */
  constructor(
    callback: Function,
    call_interval: number,
    stop_after: number,
    call_after?: number,
    stop_callback?: Function
  )
  • start : 启动定时器
  • pause : 暂停定时器
  • resume : 恢复定时器
  • stop : 停止计时器
  • restart : 重启定时器
  • elapse : 当前计时
  • rest : 剩余计时

用法

import Timer from "./Timer"
new Timer(
  function callback(timer: Timer) {
    console.log(timer.elapse / 1000 + "s");
  },
  1,
  10,
  0,
  function onStop(timer: Timer) {
    timer.restart();
  }
).start();

源码展示

IdGenerator.ts

/**
 * 运行时Id生成器
 */
class __IdGenerator {
  private id: number = 0;
  private category: string = "";

  /**
   * Id生成器构造器
   * @param category 类型
   */
  constructor(category: string) {
    this.category = category || "default";
    this.id = 0 | (Math.random() * 998);
  }

  /**
   * 获取新的id
   */
  next() {
    return this.category + "." + ++this.id;
  }
}

export namespace IdGenerator {
  export let timer = new __IdGenerator("timer");
}

Timer.ts

import { IdGenerator } from "./IdGenerator";

/**
 * 基于本地时间的定时器
 */
export default class Timer {
  //定时器标识
  public category: string;
  //已经计时
  private time_elapse: number;
  //心跳计时器
  private tick_counter: any;
  //记录开始时间
  private start_at: number;
  //毫秒后调用
  private call_after: number;
  //毫秒后暂停
  private stop_after: number;
  //计时间隔
  private call_interval: number;
  //计时回调
  private callback: Function;
  //计时回调
  private stop_callback: Function;
  //运行状态
  private state: "ready" | "running" | "paused" | "stopped";

  /**
   * 定时器构造器
   * @summary 构造时使用秒为单位,实际会转换成毫秒
   * @param callback 定时器回调
   * @param call_interval 定时器调用间隔(s)
   * @param stop_after 停止时间(s)
   * @param call_after 延迟时间(s)
   */
  constructor(
    callback: Function,
    call_interval: number,
    stop_after: number,
    call_after?: number,
    stop_callback?: Function
  ) {
    this.category = IdGenerator.timer.next();
    this.callback = callback;
    this.call_interval = call_interval * 1000;
    this.stop_after = stop_after * 1000;
    this.call_after = (call_after || 0) * 1000;
    this.stop_callback = stop_callback || idleHandler;
    this.reset();
  }

  /**
   * 重启定时器
   */
  restart() {
    this.stop();
    this.reset();
    this.start();
  }

  /**
   * 启动定时器
   */
  start() {
    if (this.tick_counter !== null) {
      return;
    }
    let time_out_id = setTimeout(() => {
      clearTimeout(time_out_id);
      this.start_at = this.now();
      this.state = "running";
      this.dump();
      this.tick_counter = setInterval(() => {
        if (this.state === "running") {
          this.callback(this);
          if (this.elapse >= this.stop_after) {
            this.stop();
            this.stop_callback(this);
          }
        }
      }, this.call_interval);
    }, this.call_after);
  }

  /**
   * 当前时间
   */
  private now(): number {
    return Date.now().valueOf();
  }

  /**
   * 获得当前计时(ms)
   * @returns number 当前计时(ms)
   */
  get elapse(): number {
    let elapse = 0;
    if (this.state === "running") {
      elapse = this.time_elapse + this.now() - this.start_at;
    } else {
      elapse = this.time_elapse;
    }
    return Math.min(elapse, this.stop_after);
  }

  /**
   * 获得剩余计时(ms)
   * @returns number 剩余计时(ms)
   */
  get rest(): number {
    return this.stop_after - this.elapse;
  }

  /**
   * 重置定时器
   */
  private reset() {
    if (this.tick_counter !== null) {
      clearInterval(this.tick_counter);
    }
    this.state = "ready";
    this.start_at = this.now();
    this.time_elapse = 0;
    this.tick_counter = null;
  }

  /**
   * 暂停定时器
   */
  pause() {
    if (this.state === "running") {
      this.time_elapse += this.now() - this.start_at;
      this.state = "paused";
      this.dump();
    }
  }

  /**
   * 恢复定时器
   */
  resume() {
    if (this.state === "paused") {
      this.start_at = this.now();
      this.state = "running";
      this.dump();
    }
  }

  /**
   * 停止计时器
   */
  stop() {
    if (this.state !== "stopped") {
      clearInterval(this.tick_counter);
      this.tick_counter = null;
      this.time_elapse += this.now() - this.start_at;
      this.time_elapse = Math.min(this.stop_after, this.time_elapse);
      this.start_at = this.now();
      this.state = "stopped";
      this.dump();
    }
  }

  //输出定时器信息
  dump() {
    let data = [
      `状态:${this.state}`,
      `当前计时: ${this.elapse}ms`,
      `剩余计时: ${this.rest}ms`
    ];
    console.group(`@定时器${this.category}信息`)
    console.log(...data);
    console.groupEnd();
  }
}

export { Timer };

相关文章

  • [TypeScript] 基于本地时间的定时器

    点击获取源码。 API constructor : 构造器 start : 启动定时器 pause : 暂停定时器...

  • Golang-基于TimeingWheel定时器

    设计思路 在linux下实现定时器主要有如下方式 基于链表实现定时器 基于排序链表实现定时器 基于最小堆实现定时器...

  • iOS三大定时器:NSTimer、CADisplayLink、G

    一、介绍NSTimer:基于Runloop实现的定时器CADisplayLink:基于Runloop实现的定时器,...

  • 安装环境

    概述 Egret基于TypeScript开发的,而TypeScript编译工具tsc是基于Node.js开发的。所...

  • Flink 定时器

    定时器 基于处理时间或者事件时间处理过一个元素之后, 注册一个定时器, 然后指定的时间执行. Context和On...

  • 多线程网络04

    1 GCD中的定时器 1.1 CFRunLoopTimerRef CFRunLoopTimerRef是基于时间的触...

  • TypeScript

    本篇文章介绍 TypeScript 的安装以及使用,不介绍 TypeScript 语法。 在 CLI 中使用 本地...

  • 读书笔记:LLD3(4)内核定时器

    内核定时器可用来在未来的某个时间点(基于时钟滴答)调度执行的某个函数。 当定时器运行时,调度定时器的进程可能正在休...

  • TKoa - 使用 TypeScript 重构的 Node.js

    ?Tkoa是使用 typescript 编写的 koa 框架! 尽管它是基于 typescript 编写,但是你依...

  • 学习笔记-TypeScript

    TypeScript TypeScript 是一门基于 JavaScript 之上的编程语言,它解决了 JavaS...

网友评论

      本文标题:[TypeScript] 基于本地时间的定时器

      本文链接:https://www.haomeiwen.com/subject/swgxghtx.html