Skip to content

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 parallel when you have multiple independent async operations and want their results collected in order.

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";
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 order
  • 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);
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 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.

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;

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 time
const 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).

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.

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");
}
}

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)[]
  • series runs tasks one after another.
  • allSettled waits for all tasks and collects outcomes.
  • race resolves with the first task to settle.
  • any resolves with the first task to fulfill.
  • reflect wraps a task to always resolve.
  • map maps over a collection with concurrency control.