{"id":10532,"library":"awaitqueue","title":"AwaitQueue","description":"AwaitQueue is a TypeScript-first utility designed to manage and execute asynchronous tasks sequentially within Node.js and browser environments. Currently stable at version 3.3.0, it provides a robust mechanism to enqueue `Promise`-returning or async functions, ensuring they run one after another, preventing concurrency issues. Key features include task naming, the ability to remove specific pending tasks, and a `stop` mechanism that rejects all currently pending tasks with custom error types. Its primary differentiator lies in its straightforward API for controlling task flow, particularly useful in scenarios requiring strict ordering, such as database writes, API calls with rate limits, or resource-intensive operations.","status":"active","version":"3.3.0","language":"javascript","source_language":"en","source_url":"https://github.com/versatica/awaitqueue","tags":["javascript","typescript"],"install":[{"cmd":"npm install awaitqueue","lang":"bash","label":"npm"},{"cmd":"yarn add awaitqueue","lang":"bash","label":"yarn"},{"cmd":"pnpm add awaitqueue","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"While CommonJS `require` is supported, ESM `import` is the recommended modern approach. The package uses named exports, not a default export.","wrong":"const AwaitQueue = require('awaitqueue');","symbol":"AwaitQueue","correct":"import { AwaitQueue } from 'awaitqueue';"},{"note":"This is a TypeScript type. Use `import type` for clarity and to ensure it's removed from compiled JavaScript output.","wrong":"import { AwaitQueuePushOptions } from 'awaitqueue';","symbol":"AwaitQueuePushOptions","correct":"import type { AwaitQueuePushOptions } from 'awaitqueue';"},{"note":"Error classes are also named exports. Direct destructuring `const { AwaitQueueStoppedError } = require('awaitqueue');` works in CommonJS.","wrong":"const AwaitQueueStoppedError = require('awaitqueue').AwaitQueueStoppedError;","symbol":"AwaitQueueStoppedError","correct":"import { AwaitQueueStoppedError } from 'awaitqueue';"}],"quickstart":{"code":"import { AwaitQueue, AwaitQueueStoppedError, AwaitQueueRemovedTaskError } from 'awaitqueue';\n\nasync function runTasks() {\n  const queue = new AwaitQueue();\n  console.log('Queue created. Size:', queue.size);\n\n  // Task 1: A simple resolving task\n  queue.push(async () => {\n    console.log('Task 1: Starting (2s)');\n    await new Promise(resolve => setTimeout(resolve, 2000));\n    console.log('Task 1: Completed');\n    return 'Result 1';\n  }, 'task-one').then(res => console.log(`Task 1 resolved with: ${res}`)).catch(err => console.error(`Task 1 failed: ${err.message}`));\n\n  // Task 2: A task that takes longer\n  queue.push(async () => {\n    console.log('Task 2: Starting (5s)');\n    await new Promise(resolve => setTimeout(resolve, 5000));\n    console.log('Task 2: Completed');\n    return 'Result 2';\n  }, 'task-two').then(res => console.log(`Task 2 resolved with: ${res}`)).catch(err => console.error(`Task 2 failed: ${err.message}`));\n\n  // Task 3: A task to be removed\n  const task3Promise = queue.push(async () => {\n    console.log('Task 3: Should not run');\n    return 'Result 3';\n  }, 'task-three');\n  task3Promise.then(res => console.log(`Task 3 resolved with: ${res}`)).catch(err => {\n    if (err instanceof AwaitQueueRemovedTaskError) {\n      console.warn(`Task 3 was removed: ${err.message}`);\n    } else {\n      console.error(`Task 3 failed: ${err.message}`);\n    }\n  });\n\n  // Task 4: A task to be stopped (after Task 2, but before its completion)\n  const task4Promise = queue.push(async () => {\n    console.log('Task 4: Should be stopped');\n    await new Promise(resolve => setTimeout(resolve, 1000));\n    return 'Result 4';\n  }, 'task-four');\n  task4Promise.then(res => console.log(`Task 4 resolved with: ${res}`)).catch(err => {\n    if (err instanceof AwaitQueueStoppedError) {\n      console.warn(`Task 4 was stopped: ${err.message}`);\n    } else {\n      console.error(`Task 4 failed: ${err.message}`);\n    }\n  });\n\n  console.log('Initial queue size:', queue.size);\n  console.log('Dumping queue:', queue.dump());\n\n  // Simulate actions after some time\n  await new Promise(resolve => setTimeout(resolve, 3000)); // Wait for Task 1 to finish and Task 2 to start\n\n  console.log('Removing Task 3 (index 1 in 0-indexed dump after Task 1 ran)');\n  queue.remove(1); // Task 3 is at index 1 after Task 1 finishes and Task 2 is at index 0\n\n  await new Promise(resolve => setTimeout(resolve, 2000)); // Wait a bit more\n\n  console.log('Stopping the queue. All remaining pending tasks will be rejected.');\n  queue.stop();\n\n  console.log('Final queue size:', queue.size);\n  console.log('Dumping queue after stop:', queue.dump());\n}\n\nrunTasks().catch(console.error);\n","lang":"typescript","description":"Demonstrates the creation and usage of AwaitQueue, enqueuing multiple asynchronous tasks, and handling task removal and queue stoppage with specific error types. It shows how tasks run sequentially and how to react to their outcomes."},"warnings":[{"fix":"Upgrade your Node.js environment to version 20 or newer. Use a Node Version Manager (NVM) to manage multiple Node.js versions.","message":"Version 3.x of `awaitqueue` requires Node.js version 20 or higher. Older Node.js environments (e.g., Node.js 18 or lower) are not supported and will lead to runtime errors or unexpected behavior.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Always add `.catch()` handlers to `awaitQueue.push()` calls or wrap `await` calls in `try...catch` blocks, explicitly checking for `instanceof AwaitQueueRemovedTaskError` and `instanceof AwaitQueueStoppedError`.","message":"When tasks are removed via `awaitQueue.remove()` or the entire queue is stopped via `awaitQueue.stop()`, the `push()` call for those tasks will reject with specific error instances: `AwaitQueueRemovedTaskError` and `AwaitQueueStoppedError`, respectively. Failing to catch these specific errors can result in unhandled promise rejections.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Be mindful when assigning names to tasks and using `removeOngoingTasksWithSameName`. Ensure your application logic correctly handles the potential rejection of prior tasks with `AwaitQueueRemovedTaskError`.","message":"Using the `removeOngoingTasksWithSameName: true` option in `awaitQueue.push()` will implicitly reject any already enqueued tasks that share the same name. This behavior might be unexpected if not explicitly accounted for, leading to tasks being prematurely cancelled.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"For CommonJS, use `const { AwaitQueue } = require('awaitqueue');`. For ES Modules, ensure your `package.json` specifies `\"type\": \"module\"` or your file has a `.mjs` extension, and use `import { AwaitQueue } from 'awaitqueue';`.","cause":"Attempting to import `AwaitQueue` incorrectly in CommonJS, e.g., `const AwaitQueue = require('awaitqueue');` which expects a default export, but `awaitqueue` uses named exports. Or trying to use `require` in an ES Module context.","error":"TypeError: AwaitQueue is not a constructor"},{"fix":"Ensure all calls to `awaitQueue.push()` are followed by a `.catch()` block or are `await`ed within a `try...catch` block, explicitly handling `AwaitQueueStoppedError`.","cause":"A task was enqueued and then the `awaitQueue.stop()` method was called, but the promise returned by `awaitQueue.push()` was not caught.","error":"UnhandledPromiseRejectionWarning: AwaitQueueStoppedError: Queue stopped"},{"fix":"The `task` argument for `awaitQueue.push()` must be a function, typically an `async` function or one that returns a `Promise`. Ensure you are passing `() => Promise<T>` or `async () => T`.","cause":"Passing a non-function or an invalid function type to `awaitQueue.push()`. The `task` argument must be a function that returns a value or a Promise.","error":"This expression is not callable. Type 'unknown' has no call signatures. Did you mean to call it with 'new'?"}],"ecosystem":"npm"}