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.
npm run import -- "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,
}
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
timers
is an object used to store timer functions with their corresponding expiration times.mainTimer
is a timer that calls the callResolve
function every 20 milliseconds.timers
object and checks if the current time is greater than each expiration time.timers
object.timers
object with the current time plus the specified delay.addResolve
function.wait
function to repeatedly check the condition and wait for a short duration.timeout
, delay
, and wait
.