export type ErrorCallback = (error: Error | null) => void; export function last(things: T[]): T | undefined { return things.length ? things[things.length - 1] : undefined; } export function tick(task: () => void) { process.nextTick(task); } export interface Queue { push(task: Task): void; onDone(task: Task): void; } interface Task { (): void; } export function queue(): Queue { const taskQueue: Task[] = []; let ongoing = false; let callbacks: Task[] = []; const execute = () => { const next = taskQueue.shift(); if (next !== undefined) { try { next(); } finally { process.nextTick(execute); } } else { ongoing = false; callbacks.forEach((task) => process.nextTick(task)); callbacks = []; } }; return { push(task: Task) { taskQueue.push(task); if (!ongoing) { ongoing = true; process.nextTick(execute); } }, onDone(task: Task) { if (ongoing) { callbacks.push(task); } else { process.nextTick(task); } }, }; }