UNPKG

tiny-essentials

Version:

Collection of small, essential scripts designed to be used across various projects. These simple utilities are crafted for speed, ease of use, and versatility.

222 lines (161 loc) 8.1 kB
# `TinyPromiseQueue` Documentation 🎉 `TinyPromiseQueue` is a queue system designed to manage and execute asynchronous tasks in a sequential, one-at-a-time order. Tasks are executed in the order they are added to the queue, with support for optional delays ⏳, task cancellation ❌, and task reordering 🔄. --- ## Properties 🏠 - **`#queue`**: The internal queue array that holds all the tasks. - **`#running`**: A flag indicating whether the queue is currently processing a task. - **`#timeouts`**: An object storing timeouts for scheduled delays. - **`#blacklist`**: A set of task IDs that should be skipped if already being processed or canceled. --- ## Methods 🛠️ ### `isRunning()` 🏃‍♀️ Returns whether the queue is currently processing a task. #### Returns: - `boolean`: `true` if the queue is processing a task, otherwise `false`. --- ### `getIndexById(id)` 🔍 Returns the index of a task in the queue by its ID. #### Parameters: - `id` (`string`): The ID of the task to locate. #### Returns: - `number`: The index of the task in the queue, or `-1` if not found. --- ### `getQueuedIds()` 📋 Returns a list of IDs for all tasks currently in the queue. #### Returns: - `Array<{ index: number, id: string }>`: An array of task IDs and their corresponding indices. --- ### `reorderQueue(fromIndex, toIndex)` 🔄 Reorders a task in the queue from one index to another. #### Parameters: - `fromIndex` (`number`): The current index of the task to move. - `toIndex` (`number`): The index where the task should be placed. #### Returns: - `void`: This method does not return anything. --- ### `enqueue(task, delay, id)` ⏳ Adds a new async task to the queue and ensures it runs in order after previous tasks. Optionally, a delay can be added before the task is executed. If the task is canceled before execution, it will be rejected with the message: **"The function was canceled on TinyPromiseQueue."** #### Parameters: - `task` (`Function`): A function that returns a `Promise` to be executed sequentially. - `delay` (`number|null`): Optional delay (in ms) before the task is executed. - `id` (`string`): Optional ID to identify the task in the queue. #### Returns: - `Promise<any>`: A promise that resolves or rejects with the result of the task once it's processed. --- ### `enqueuePoint(task, id)` 🪢 Adds an async task to a parallel group in the queue. All tasks added with `enqueuePoint` before the next `enqueue` will be executed **simultaneously**, but only after all previous tasks in the queue have completed. These grouped tasks share a "concurrent checkpoint" and will run using `Promise.all`. Each task resolves or rejects independently. If a task is canceled before execution, it will be rejected with the message: **"The function was canceled on TinyPromiseQueue."** #### Parameters: - `task` (`Function`): A function that returns a `Promise` to be executed sequentially. - `id` (`string`): Optional ID to identify the task in the queue. #### Returns: - `Promise<any>`: A promise that resolves or rejects with the result of the task once it's processed. --- ### `cancelTask(id)` ❌ Cancels a scheduled delay and removes the task from the queue. Adds the ID to a blacklist so the task is skipped if already being processed. #### Parameters: - `id` (`string`): The ID of the task to cancel. #### Returns: - `boolean`: `true` if a delay was cancelled and the task was removed, otherwise `false`. --- ## Usage Example 💻 ```js import { TinyPromiseQueue } from './TinyPromiseQueue'; const queue = new TinyPromiseQueue(); // Helper function to create simple tasks with logs function createTask(name, duration = 500) { return () => new Promise((resolve) => { console.log(`Started task: ${name}`); setTimeout(() => { console.log(`Finished task: ${name}`); resolve(name); }, duration); }); } // Enqueue 3 tasks queue.enqueue(createTask('A'), 100, 'taskA'); queue.enqueue(createTask('B'), 0, 'taskB'); queue.enqueue(createTask('C'), 0, 'taskC'); // Wait for 50ms and cancel taskB setTimeout(() => { const success = queue.cancelTask('taskB'); console.log('Canceled taskB:', success); // true if cancelled }, 50); // List the remaining IDs in the queue setTimeout(() => { const ids = queue.getQueuedIds(); console.log('Queued IDs:', ids); }, 60); ``` ```js import { TinyPromiseQueue } from './TinyPromiseQueue'; const queue = new TinyPromiseQueue(); await new Promise((resolve) => { // Task generator with color-coded logs function createTask(name, duration = 500) { return () => new Promise((resolve) => { console.log(`\x1b[34m[STARTED]\x1b[0m \x1b[36m${name}\x1b[0m`); setTimeout(() => { console.log(`\x1b[32m[FINISHED]\x1b[0m \x1b[36m${name}\x1b[0m`); resolve(name); }, duration); }); } // Function to simulate a parallel group of enqueues const parallelEnqueueGroup = (groupName, delayStart = 0) => { const count = Math.floor(Math.random() * (15 - 1 + 1) + 1); for (let i = 1; i <= count; i++) { const taskName = `${groupName}-${i}`; queue.enqueue(createTask(taskName, 300 + i * 50), delayStart, taskName); } }; // Main enqueue block queue.enqueue(createTask('Init-1', 400), 50, 'init-1'); queue.enqueue(createTask('Init-2', 400), 0, 'init-2'); // Simulate enqueues from other contexts "in parallel" parallelEnqueueGroup('Alpha', 80); // Starts after 80ms parallelEnqueueGroup('Beta', 120); // Starts after 120ms parallelEnqueueGroup('Gamma', 250); // Starts after 250ms parallelEnqueueGroup('Delta', 180); // Starts after 180ms parallelEnqueueGroup('Epsilon', 300); // Starts after 300ms parallelEnqueueGroup('Zeta', 160); // Starts after 160ms parallelEnqueueGroup('Eta', 90); // Starts after 90ms parallelEnqueueGroup('Theta', 220); // Starts after 220ms parallelEnqueueGroup('Iota', 140); // Starts after 140ms parallelEnqueueGroup('Kappa', 400); // Starts after 400ms parallelEnqueueGroup('Lambda', 190); // Starts after 190ms parallelEnqueueGroup('Mu', 260); // Starts after 260ms parallelEnqueueGroup('Nu', 110); // Starts after 110ms parallelEnqueueGroup('Xi', 330); // Starts after 330ms parallelEnqueueGroup('Omicron', 170); // Starts after 170ms parallelEnqueueGroup('Pi', 280); // Starts after 280ms parallelEnqueueGroup('Rho', 70); // Starts after 70ms parallelEnqueueGroup('Sigma', 360); // Starts after 360ms parallelEnqueueGroup('Tau', 130); // Starts after 130ms parallelEnqueueGroup('Upsilon', 240); // Starts after 240ms parallelEnqueueGroup('Phi', 310); // Starts after 310ms parallelEnqueueGroup('Chi', 100); // Starts after 100ms parallelEnqueueGroup('Psi', 200); // Starts after 200ms parallelEnqueueGroup('Omega', 50); // Starts after 50ms // Final task to confirm everything executed setTimeout(() => { queue.enqueue(createTask('Finalizer', 500), 0, 'finalizer').then(() => { console.log('\x1b[35m[QUEUE COMPLETE]\x1b[0m All tasks have been processed.'); resolve(); }); }, 250); }); ``` ### Explanation 🧩: 1. **Task Creation**: Tasks are created with a name and an optional duration (in ms). The task logs its start and finish times 🕰️. 2. **Task Execution**: Tasks are enqueued one at a time, ensuring they run in the order they were added 🔁. 3. **Cancellation**: After 50ms, taskB is canceled, demonstrating the ability to remove a task from the queue ❌. 4. **Remaining Tasks**: The remaining tasks in the queue are logged after 60ms 📊. --- ## Conclusion 🎯 `TinyPromiseQueue` provides a simple and effective way to manage a sequence of asynchronous tasks. With its support for delays ⏳, task cancellation ❌, and reordering 🔄, it allows for efficient control over task execution in JavaScript.