Gathering detailed insights and metrics for @digitalwalletcorp/promise-concurrent-executor
Gathering detailed insights and metrics for @digitalwalletcorp/promise-concurrent-executor
Gathering detailed insights and metrics for @digitalwalletcorp/promise-concurrent-executor
Gathering detailed insights and metrics for @digitalwalletcorp/promise-concurrent-executor
A JavaScript library to control Promise concurrency. It processes asynchronous tasks up to a specified limit, offering queuing and automated execution. Ideal for stabilizing async operations, preventing excessive resource consumption, and improving application performance by managing the flow of API calls or data processing.
npm install @digitalwalletcorp/promise-concurrent-executor
Typescript
Module System
Node Version
NPM Version
TypeScript (100%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
27 Commits
2 Branches
3 Contributors
Updated on Jun 11, 2025
Latest Version
1.0.7
Package Id
@digitalwalletcorp/promise-concurrent-executor@1.0.7
Unpacked Size
48.14 kB
Size
12.88 kB
File Count
11
NPM Version
10.2.4
Node Version
20.11.0
Published on
Jun 11, 2025
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
5
A JavaScript library to control Promise concurrency. It processes asynchronous tasks up to a specified limit, offering queuing and automated execution. Ideal for stabilizing async operations, preventing excessive resource consumption, and improving application performance by managing the flow of API calls or data processing.
This library is Isomorphic / Universal, meaning it is designed to run in multiple JavaScript environments. It has no dependencies on platform-specific APIs.
1npm install @digitalwalletcorp/promise-concurrent-executor 2# or 3yarn add @digitalwalletcorp/promise-concurrent-executor
The PromiseConcurrentExecutor
helps you manage a queue of asynchronous tasks, ensuring that only a specified number run in parallel. You can add tasks to the queue and then trigger their execution using executeAll
or executeAllSettled
.
executeAll
vs. executeAllSettled
Both methods execute all queued Promise functions, but they handle rejected Promises differently:
executeAll<T>()
: Similar to Promise.all()
, this method starts all queued Promise functions and awaits their completion. If any of the Promises reject, executeAll
will immediately reject with the reason of the first Promise that failed. The return type supports array or tuple types for its generic T
.executeAllSettled<T>()
: Similar to Promise.allSettled()
, this method executes all queued Promise functions regardless of whether they succeed or fail. It always returns an array of PromiseSettledResult
objects, where each object indicates the status ('fulfilled'
or 'rejected'
) and the value
or reason
. This is useful when you want to inspect the outcome of every task. For its generic T
, it only supports a single type, not array or tuple types. If the return types of your functions vary, you should omit T
or use any
.executeAll
ExampleCore Concept: Managing a Queue of Tasks
This example demonstrates the core functionality of the library. We will add 10 asynchronous tasks to the executor
, which is configured with a concurrency limit of 3. The executor
runs a maximum of 3 tasks in parallel. As one task finishes, the next one from the queue is automatically started, ensuring the concurrency limit is respected until all 10 tasks are complete.
1import { PromiseConcurrentExecutor } from '@digitalwalletcorp/promise-concurrent-executor'; 2 3// A mock async function that simulates a task with a variable delay 4const asyncTask = (id: number): Promise<string> => { 5 return new Promise(resolve => { 6 const delay = Math.floor(Math.random() * 500) + 200; // Random delay between 200ms and 700ms 7 console.log(` -> Task ${id} started (delay: ${delay}ms)`); 8 setTimeout(() => { 9 console.log(` <- Task ${id} finished.`); 10 resolve(`Result from task ${id}`); 11 }, delay); 12 }); 13}; 14 15// 1. Initialize with a concurrency of 3 16const executor = new PromiseConcurrentExecutor(3); 17 18// 2. Add 10 tasks to the queue 19console.log('Adding 10 tasks to the queue...'); 20for (let i = 1; i <= 10; i++) { 21 executor.add(() => asyncTask(i)); 22} 23 24// 3. Start execution and wait for all tasks to complete 25console.log(`Starting execution with concurrency=3. Queue size=${executor.size()}`); 26const results = await executor.executeAll<string[]>(); 27 28console.log('\n✅ All tasks completed successfully!'); 29console.log('Results:', results); 30 31/* Expected Output (the exact order of start/finish logs will vary): 32Adding 10 tasks to the queue... 33Starting execution with concurrency=3. Queue size=10 34 -> Task 1 started (delay: ...ms) 35 -> Task 2 started (delay: ...ms) 36 -> Task 3 started (delay: ...ms) 37 // -- At this point, 3 tasks are running. Task 4 must wait. 38 <- Task 2 finished. 39 -> Task 4 started (delay: ...ms) // -- Task 2 finished, so Task 4 begins. 40 <- Task 1 finished. 41 -> Task 5 started (delay: ...ms) // -- And so on... 42 ... 43 <- Task 10 finished. 44 45✅ All tasks completed successfully! 46Results: [ 47 'Result from task 1', 48 'Result from task 2', 49 'Result from task 3', 50 'Result from task 4', 51 'Result from task 5', 52 'Result from task 6', 53 'Result from task 7', 54 'Result from task 8', 55 'Result from task 9', 56 'Result from task 10' 57] 58*/
executeAll
ExamplesThe following examples demonstrate other key features of executeAll
, such as handling mixed return types and, importantly, its "fail-fast" error handling behavior where execution stops as soon as a task fails.
1// Example: Handling different return types using a tuple 2const executor2 = new PromiseConcurrentExecutor(2); 3executor2.add(async () => 'string_result'); 4executor2.add(async () => 123); 5const results2 = await executor2.executeAll<[string, number]>(); 6console.log('Mixed type results:', results2); // -> ['string_result', 123] 7 8// Example: Error handling 9const executor3 = new PromiseConcurrentExecutor(2); 10executor3.add(async () => 'Success'); 11executor3.add(async () => { throw new Error('Failure'); }); 12try { 13 await executor3.executeAll(); 14} catch (error: any) { 15 // executeAll rejects as soon as one promise fails. 16 console.error('Execution failed:', error.message); // -> Execution failed: Failure 17}
executeAllSettled
ExampleIn contrast to the "fail-fast" behavior of executeAll
, executeAllSettled
is designed with a "run-to-completion" approach. It guarantees that every task in the queue will be executed, regardless of whether some of them fail.
The executeAllSettled
promise itself never rejects due to task failures. Instead, it always resolves with an array of result objects, each detailing the outcome ('fulfilled'
or 'rejected'
) of a task. This allows you to safely inspect every result, making it ideal for scenarios where comprehensive processing and reliable error logging are critical.
The following example demonstrates this by running a mix of succeeding and failing tasks.
1import { PromiseConcurrentExecutor } from '@digitalwalletcorp/promise-concurrent-executor'; 2 3// 1. Initialize with a concurrency of 3 4const executor = new PromiseConcurrentExecutor(3); 5 6// 2. Add 7 tasks that may succeed or fail 7console.log('Adding 7 tasks (odd # will succeed, even # will fail)...'); 8for (let i = 1; i <= 7; i++) { 9 executor.add(() => new Promise((resolve, reject) => { 10 const delay = Math.random() * 200 + 50; 11 console.log(` -> Task ${i} processing...`); 12 setTimeout(() => { 13 if (i % 2 !== 0) { // Succeed if 'i' is odd 14 resolve(`Task ${i} Succeeded`); 15 } else { // Fail if 'i' is even 16 reject(new Error(`Task ${i} Failed`)); 17 } 18 }, delay); 19 })); 20} 21 22// 3. Execute and wait for all tasks to settle 23console.log('\nStarting executeAllSettled...'); 24// The generic type <string> refers to the *fulfilled* value type. 25const settledResults = await executor.executeAllSettled<string>(); 26 27console.log('\n✅ All tasks have settled.'); 28settledResults.forEach((result, index) => { 29 if (result.status === 'fulfilled') { 30 console.log(` Task ${index + 1}: FULFILLED, Value: "${result.value}"`); 31 } else { 32 // result.reason is the error that was thrown 33 console.error(` Task ${index + 1}: REJECTED, Reason: ${result.reason.message}`); 34 } 35}); 36 37/* Expected Output (order of processing logs will vary): 38Adding 7 tasks... 39... 40Starting executeAllSettled... 41 -> Task 1 processing... 42 -> Task 2 processing... 43 -> Task 3 processing... 44... 45✅ All tasks have settled. 46 Task 1: FULFILLED, Value: "Task 1 Succeeded" 47 Task 2: REJECTED, Reason: Task 2 Failed 48 Task 3: FULFILLED, Value: "Task 3 Succeeded" 49 Task 4: REJECTED, Reason: Task 4 Failed 50 Task 5: FULFILLED, Value: "Task 5 Succeeded" 51 Task 6: REJECTED, Reason: Task 6 Failed 52 Task 7: FULFILLED, Value: "Task 7 Succeeded" 53*/
new PromiseConcurrentExecutor(concurrency?: number, options?: PromiseConcurrentExecutorOption)
concurrency
(optional, default: 1
): The maximum number of Promises to execute in parallel.options
(optional): An object with configuration options.1export interface PromiseConcurrentExecutorOption { 2 /** Delay between checks for available concurrency (in milliseconds). Default: 100ms */ 3 interval?: number; 4 /** Automatic execution settings */ 5 autoExecute?: { 6 /** Type of execution: 'all' or 'allSettled' */ 7 type: 'all' | 'allSettled'; 8 /** Number of queued functions that triggers automatic execution. When the queue size reaches this threshold, all currently queued functions will be executed. */ 9 triggerThreshold: number; 10 }; 11}
add(asyncFunction: () => Promise<any>): void
Adds an asynchronous function (wrapped in a Promise) to the execution queue.
Note: You cannot add functions while executeAll
or executeAllSettled
is in progress.
addWithAutoExecute(asyncFunction: () => Promise<any>, options?: PromiseConcurrentExecutorOption): Promise<void>
Adds an asynchronous function to the queue. If autoExecute
options are set (either in constructor options or provided here), it will automatically trigger execution (executeAll
or executeAllSettled
) when triggerThreshold
is met.
Important: Always await
this function to prevent potential race conditions where execution might start while you're still adding tasks. This method does not return execution results to avoid memory pressure during automatic execution of large numbers of tasks.
addAll(asyncFunctions: (() => Promise<any>[]): void
Adds multiple asynchronous functions to the execution queue. Similar to add
.
addAllWithAutoExecute(asyncFunctions: (() => Promise<any>[]), options?: PromiseConcurrentExecutorOption): Promise<void>
Adds multiple asynchronous functions to the queue, with potential auto-execution. Similar to addWithAutoExecute
.
executeAllSettled<T = any>(options?: PromiseConcurrentExecutorOption): Promise<PromiseSettledResult<T>[]>
Starts the execution of all queued Promise functions. It waits for all Promises to settle (either fulfill or reject) and returns an array of PromiseSettledResult<T>
.
executeAll<T = any[]>(options?: PromiseConcurrentExecutorOption): Promise<Awaited<T>>
Starts the execution of all queued Promise functions. It waits for all Promises to fulfill. If any Promise rejects, the entire execution will immediately reject. Returns an array of resolved values.
getConcurrency(): number
Returns the current maximum parallel execution limit.
setConcurrency(concurrency: number): void
Sets a new maximum parallel execution limit.
size(): number
Returns the number of functions currently in the queue.
This project is licensed under the MIT License. See the LICENSE file for details.
This README covers the basic setup and primary usage of the library. For more advanced use cases and a comprehensive look at all features, the test suite serves as practical and up-to-date documentation.
We recommend Browse the test files to discover:
You can find the test case in the /test/specs
directory of our GitHub repository.
No vulnerabilities found.
No security vulnerabilities found.