discord | discord users | delete all commands | Search

This code implements a timer system that stores and manages multiple timers with their corresponding expiration times, allowing for functions to be executed at specified intervals. The system exports three functions: timeout for creating promises that resolve after a delay, delay for waiting for a specified time, and wait for conditional waiting.

Run example

npm run import -- "discord utilities"

discord utilities

var timers = {}
var mainTimer = setInterval(callResolve, 20)

function callResolve() {
  var now = Date.now()
  var times = Object.keys(timers)
  for(var i = 0; i < times.length; i++) {
    if(now > times[i]) {
      try {
        Promise.resolve(timers[times[i]]())
      } catch (e) {
        console.log('timer failed', e)
        throw e
      }
      delete timers[times[i]]
      return
    }
  }
}

function addResolve(resolve, time) {
  while(typeof timers[time] != 'undefined') {
    time++
  }
  timers[time] = resolve
}

async function timeout(delay) {
  var now = Date.now()
  await new Promise(resolve => addResolve(resolve, now + delay))  
}

async function delay(prev, delay) {
  var now = Date.now()
  if(now - prev < delay)
    await new Promise(resolve => addResolve(resolve, now + (delay - (now - prev))))
  return Date.now()
}

async function wait(until, delay) {
  var waitTimer
  var waitCount = 0
  var result
  var now = Date.now()
  var delayed = now + delay
  while(!result && now < delayed) {
    await timeout(100)
    result = await until()
    now = Date.now()
  }
  return result
}

module.exports = {
  timeout,
  delay,
  wait,
}

What the code could have been:

class TimerManager {
  /**
   * Creates a new instance of TimerManager.
   */
  constructor() {
    this.timers = {}
    this.mainTimer = setInterval(this.callResolve.bind(this), 20)
  }

  /**
   * Call resolve function for expired timers.
   */
  callResolve() {
    const now = Date.now()
    const times = Object.keys(this.timers)
    for (const time of times) {
      if (now > Number(time)) {
        try {
          Promise.resolve(this.timers[time]())
          delete this.timers[time]
        } catch (e) {
          console.log('timer failed', e)
          throw e
        }
      }
    }
  }

  /**
   * Add a resolve function to the timer queue.
   * @param {function} resolve - The resolve function to be added.
   * @param {number} time - The time when the resolve function should be called.
   */
  addResolve(resolve, time) {
    while (this.timers[time]!== undefined) {
      time++
    }
    this.timers[time] = resolve
  }

  /**
   * Create a promise that resolves after a specified delay.
   * @param {number} delay - The delay in milliseconds.
   * @returns {Promise}
   */
  async timeout(delay) {
    const now = Date.now()
    await new Promise(resolve => this.addResolve(resolve, now + delay))  
  }

  /**
   * Delay for a specified time.
   * @param {number} prev - The previous time.
   * @param {number} delay - The delay in milliseconds.
   * @returns {Promise} The current time.
   */
  async delay(prev, delay) {
    const now = Date.now()
    if (now - prev < delay) {
      await this.timeout(delay - (now - prev))
    }
    return Date.now()
  }

  /**
   * Wait for a specified condition to be met.
   * @param {function} until - The condition to be met.
   * @param {number} delay - The delay in milliseconds.
   * @returns {Promise} The result of the condition.
   */
  async wait(until, delay) {
    let waitTimer
    let waitCount = 0
    let result
    const now = Date.now()
    const delayed = now + delay
    while (!result && now < delayed) {
      await this.timeout(100)
      result = await until()
      now = Date.now()
    }
    return result
  }

  /**
   * Clean up the timer queue.
   */
  cleanup() {
    clearInterval(this.mainTimer)
    this.mainTimer = null
    this.timers = {}
  }
}

module.exports = TimerManager

Code Breakdown

Variables and Timers

callResolve Function

addResolve Function

timeout Function

delay Function

wait Function

Exports