parallel
parallel executes multiple async tasks concurrently and collects their results in order. It is also exported as all for familiarity with Promise.all.
Best for independent tasks Use
parallelwhen you have multiple independent async operations and want their results collected in order.
Import
Section titled “Import”Root package:
import { parallel, all } from "@vgerbot/async";Module subpath:
import { parallel, all } from "@vgerbot/async/control-flow";Leaf subpath:
import { parallel } from "@vgerbot/async/control-flow/parallel";Quick example
Section titled “Quick example”import { parallel } from "@vgerbot/async";
const handle = parallel( { concurrency: 2 }, async (token) => { await token.sleep(100); return "a"; }, async (token) => { await token.sleep(50); return "b"; }, async (token) => { await token.sleep(75); return "c"; },);
const results = await handle;// ["a", "b", "c"] — results are in the original orderWhen to use parallel
Section titled “When to use parallel”- Independent operations: Fetch multiple resources, process multiple files, or call multiple APIs simultaneously.
- Controlled concurrency: Limit the number of simultaneous operations to avoid overwhelming resources.
- Ordered results: Collect results in the same order as the input tasks, regardless of completion order.
- Cancellable batches: Cancel the entire batch when the result is no longer needed.
function parallel( options: ParallelOptions, ...tasks: AsyncTask<unknown>[]): CancellableHandle<unknown[]>;all is an alias for parallel:
import { all } from "@vgerbot/async";
const results = await all({ concurrency: 2 }, task1, task2);Parameters
Section titled “Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
options |
ParallelOptions |
— | Configuration options, including concurrency and cancellation settings. |
...tasks |
AsyncTask<T>[] |
— | Rest parameters of async tasks to execute. Each receives a CancellableToken. |
ParallelOptions
Section titled “ParallelOptions”ParallelOptions extends CancellableOptions<T[]> with:
| Option | Type | Default | Description |
|---|---|---|---|
concurrency |
number |
Infinity |
Maximum number of tasks running simultaneously. |
name |
string |
"parallel" |
Name used in cancellation labels. |
signal |
AbortSignal |
undefined |
External signal linked to the batch. |
timeout |
number |
undefined |
Cancels the batch after the specified milliseconds. |
fallback |
value or function | undefined |
Fallback value used when the batch rejects. |
retry |
RetryOptions |
undefined |
Retry configuration applied to the whole batch. |
Return value
Section titled “Return value”Returns a CancellableHandle<T[]> that resolves to an array of results in the same order as the input tasks.
const handle = parallel({ concurrency: 3 }, task1, task2, task3);
const results = await handle;handle.cancel("No longer needed");handle.isCancelled();handle.signal;Execution model
Section titled “Execution model”parallel uses a slot-filling concurrency limiter. When concurrency is finite, it starts at most N tasks simultaneously. As soon as one completes, the next pending task starts. Results are collected in the original input order.
// With concurrency: 2, at most 2 tasks run at any timeconst handle = parallel( { concurrency: 2 }, async (token) => { await token.sleep(100); return 1; }, async (token) => { await token.sleep(50); return 2; }, async (token) => { await token.sleep(75); return 3; }, async (token) => { await token.sleep(25); return 4; },);
const results = await handle; // [1, 2, 3, 4]Without a concurrency limit, all tasks start immediately (equivalent to Promise.all).
Error handling
Section titled “Error handling”If any task rejects, parallel rejects with the first error. Other in-flight tasks are not cancelled automatically—they will continue to run, but their results are discarded.
try { await parallel({}, async () => "ok", async () => { throw new Error("fail"); }, async () => "also ok", );} catch (error) { console.log("Parallel failed:", error);}To collect all results regardless of failures, use allSettled or wrap individual tasks with reflect.
Cancellation
Section titled “Cancellation”All tasks share a single CancellableToken. Calling cancel() on the handle signals cancellation to all running tasks.
const handle = parallel( { concurrency: 3, name: "batchFetch" }, ...Array.from({ length: 10 }, (_, i) => async (token) => { await token.sleep(1000); return i; } ),);
setTimeout(() => handle.cancel("User navigated away"), 500);
try { await handle;} catch (error) { if (error instanceof CancelError) { console.log("Batch was cancelled"); }}TypeScript tips
Section titled “TypeScript tips”parallel is generic over T, so all tasks must return the same type T.
const handle = parallel({}, async (token) => 1, async (token) => 2, async (token) => 3,);
const results = await handle; // number[]For heterogeneous result types, use a union type or reflect:
const handle = parallel<string | number>({}, async () => "hello", async () => 42,);
const results = await handle; // (string | number)[]