Mirror of https://github.com/roostorg/coop github.com/roostorg/coop
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 557ff54b2b435e5f1e789c6a8a4e1bebf2d7deb6 61 lines 1.7 kB view raw
1import { delay } from "./utils.js"; 2 3/** 4 * Stores/runs a set of timers and can alert callers when all timers 5 * have finished, and that can be closed by callers. 6 */ 7export default class TimerSet { 8 // We have to actually store the timers (eek), 9 // not just a count, to support close functionality. 10 private readonly timers: Set<any> = new Set(); 11 private closed = false; 12 13 public setTimeout( 14 cb: (...args: any[]) => void, 15 ms: number, 16 ...args: any[] 17 ): NodeJS.Timeout { 18 if (this.closed) { 19 throw new Error("TimerSet is closed. New timers cannot be added."); 20 } 21 22 const timer = setTimeout(() => { 23 this.timers.delete(timer); 24 cb(...args); 25 }, ms); 26 27 this.timers.add(timer); 28 return timer; 29 } 30 31 public clearTimeout(timeout: NodeJS.Timeout) { 32 this.timers.delete(timeout); 33 clearTimeout(timeout); 34 } 35 36 /** 37 * Stops the set from accepting more timers and returns a promise that 38 * resolves when all known timers are done. If `timeout` ms elapse before 39 * the timers finish, it `unref`s them so they don't block the node process 40 * from closing, and then its returned promise resolves. 41 */ 42 public async close(timeout?: number) { 43 this.closed = true; 44 45 // Ironic to use a timer to poll a count of timers, but hey. 46 const timersDone = async (): Promise<void> => 47 this.timers.size === 0 ? undefined : delay(20).then(timersDone); 48 49 if (timeout === undefined) { 50 return timersDone(); 51 } 52 53 const unrefAllAfterTimeout = delay(timeout).then(() => { 54 this.timers.forEach((it) => { 55 it.unref(); 56 }); 57 }); 58 59 await Promise.race([unrefAllAfterTimeout, timersDone()]); 60 } 61}