Skip to content

any

any runs multiple async tasks concurrently and resolves with the first one to fulfill. If all tasks reject, it rejects with an AggregateError. It is the cancellable equivalent of Promise.any.

Best for first success Use any when you have multiple fallback sources and want the first successful result.

Root package:

import { any } from "@vgerbot/async";

Module subpath:

import { any } from "@vgerbot/async/control-flow";

Leaf subpath:

import { any } from "@vgerbot/async/control-flow/any";
import { any } from "@vgerbot/async";
const handle = any({},
async (token) => {
const res = await token.wrap(fetch("https://api1.example.com/data"));
if (!res.ok) throw new Error("api1 down");
return res.json();
},
async (token) => {
const res = await token.wrap(fetch("https://api2.example.com/data"));
if (!res.ok) throw new Error("api2 down");
return res.json();
},
);
const data = await handle; // First successful response
  • Redundant sources: Query multiple API endpoints and use the first that responds successfully.
  • Fallback strategies: Try multiple approaches and use whichever works first.
  • Best-effort operations: Attempt several alternatives, succeeding if any one works.
  • Cancellable batches: Cancel remaining tasks once one succeeds.
function any(
options: CancellableOptions,
...tasks: AsyncTask<unknown>[]
): CancellableHandle<unknown>;
Parameter Type Default Description
options CancellableOptions Cancellable configuration options.
...tasks AsyncTask<T>[] Rest parameters of async tasks to execute. Each receives a CancellableToken.

Returns a CancellableHandle<T> that resolves with the first task to fulfill, or rejects with an AggregateError if all tasks reject.

const handle = any({}, task1, task2);
const result = await handle;
handle.cancel("No longer needed");
handle.isCancelled();
handle.signal;

All tasks start concurrently and share a CancellableToken. The handle resolves as soon as the first task fulfills. Remaining tasks receive a cancellation signal.

const handle = any({},
async (token) => { await token.sleep(100); throw new Error("fail"); },
async (token) => { await token.sleep(200); return "success"; },
async (token) => { await token.sleep(500); return "also success"; },
);
// Resolves with "success" after 200ms
// First task's rejection is ignored
// Third task is cancelled

If all tasks reject, the handle rejects with an AggregateError containing all rejection reasons.

try {
await any({},
async () => { throw new Error("fail1"); },
async () => { throw new Error("fail2"); },
);
} catch (error) {
if (error instanceof AggregateError) {
console.log("All tasks failed:", error.errors);
}
}

Calling cancel() on the handle cancels all participating tasks.

const handle = any({ name: "anyOperation" },
async (token) => { await token.sleep(5000); return "result"; },
);
setTimeout(() => handle.cancel("User cancelled"), 100);

any is generic over T. All tasks must return the same type.

const handle = any({},
async () => 1,
async () => 2,
);
const result = await handle; // number
  • race settles with the first task to complete (fulfill or reject).
  • allSettled waits for all tasks and collects all outcomes.
  • parallel runs all tasks and collects all results.
  • tryEach tries tasks sequentially until one succeeds.