UNPKG

@tldraw/utils

Version:

tldraw infinite canvas SDK (private utilities).

119 lines (118 loc) 3.48 kB
import { sleep } from "./control.mjs"; class ExecutionQueue { /** * Creates a new ExecutionQueue. * * Creates a new execution queue that will process tasks sequentially. * If a timeout is provided, there will be a delay between each task execution, * which is useful for rate limiting or controlling execution flow. * * timeout - Optional delay in milliseconds between task executions * @example * ```ts * // Create queue without delay * const fastQueue = new ExecutionQueue() * * // Create queue with 500ms delay between tasks * const slowQueue = new ExecutionQueue(500) * ``` */ constructor(timeout) { this.timeout = timeout; } queue = []; running = false; /** * Checks if the queue is empty and not currently running a task. * * Determines whether the execution queue has completed all tasks and is idle. * Returns true only when there are no pending tasks in the queue AND no task is currently being executed. * * @returns True if the queue has no pending tasks and is not currently executing * @example * ```ts * const queue = new ExecutionQueue() * * console.log(queue.isEmpty()) // true - queue is empty * * queue.push(() => console.log('task')) * console.log(queue.isEmpty()) // false - task is running/pending * ``` */ isEmpty() { return this.queue.length === 0 && !this.running; } async run() { if (this.running) return; try { this.running = true; while (this.queue.length) { const task = this.queue.shift(); await task(); if (this.timeout) { await sleep(this.timeout); } } } finally { this.running = false; } } /** * Adds a task to the queue and returns a promise that resolves with the task's result. * * Enqueues a task for sequential execution. The task will be executed after all * previously queued tasks have completed. If a timeout was specified in the constructor, * there will be a delay between this task and the next one. * * @param task - The function to execute (can be sync or async) * @returns Promise that resolves with the task's return value * @example * ```ts * const queue = new ExecutionQueue(100) * * // Add async task * const result = await queue.push(async () => { * const response = await fetch('/api/data') * return response.json() * }) * * // Add sync task * const number = await queue.push(() => 42) * ``` */ async push(task) { return new Promise((resolve, reject) => { this.queue.push(() => Promise.resolve(task()).then(resolve).catch(reject)); this.run(); }); } /** * Clears all pending tasks from the queue. * * Immediately removes all pending tasks from the queue. Any currently * running task will complete normally, but no additional tasks will be executed. * This method does not wait for the current task to finish. * * @returns void * @example * ```ts * const queue = new ExecutionQueue() * * // Add several tasks * queue.push(() => console.log('task 1')) * queue.push(() => console.log('task 2')) * queue.push(() => console.log('task 3')) * * // Clear all pending tasks * queue.close() * // Only 'task 1' will execute if it was already running * ``` */ close() { this.queue = []; } } export { ExecutionQueue }; //# sourceMappingURL=ExecutionQueue.mjs.map