timer.class.ts 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. export class Timer {
  2. private intervalHdl?: NodeJS.Timer;
  3. private subscribers: {
  4. [id: number]: {
  5. lastTick: number;
  6. seconds: number;
  7. tick: () => void;
  8. };
  9. } = {};
  10. private static INSTANCE?: Timer;
  11. public static get instance(): Timer {
  12. if (!Timer.INSTANCE) {
  13. Timer.INSTANCE = new Timer();
  14. }
  15. return Timer.INSTANCE;
  16. }
  17. private constructor() {}
  18. public start() {
  19. if (this.intervalHdl) {
  20. return;
  21. }
  22. this.intervalHdl = setInterval(this.loop.bind(this), 1000);
  23. }
  24. private loop() {
  25. const now = new Date();
  26. Object.values(this.subscribers).forEach(sub => {
  27. if (now.getTime() >= sub.lastTick + sub.seconds * 1000) {
  28. sub.lastTick = now.getTime();
  29. sub.tick();
  30. }
  31. });
  32. }
  33. public subscribe(seconds: number, tick: () => void) {
  34. const lastTick = new Date().getTime();
  35. const id =
  36. Object.keys(this.subscribers)
  37. .map(k => Number(k))
  38. .reduce((r, id) => Math.max(r, id), 0) + 1;
  39. this.subscribers[id] = { lastTick, seconds, tick };
  40. return id;
  41. }
  42. public unsubscribe(id: number) {
  43. if (typeof this.subscribers[id] === 'function') {
  44. delete this.subscribers[id];
  45. }
  46. }
  47. public stop() {
  48. if (!this.intervalHdl) return;
  49. clearInterval(this.intervalHdl);
  50. this.intervalHdl = undefined;
  51. }
  52. }