API reference › @evolu/common › Task › firstN
function firstN<TTasks>(
tasks: TTasks,
count: Int1To100OrPositiveInt,
options?: TaskCollectionOptions,
): Task<
readonly InferTaskOk<TTasks[number]>[],
never,
ParameterIntersection<
TTasks[number] extends TTask
? TTask extends AnyTask
? (deps: InferTaskDeps<TTask>) => void
: never
: never
>
>;
Defined in: packages/common/src/Task.ts:4448
Runs Tasks until count Tasks return Ok or all Tasks settle.
Returns Ok with Ok values in settlement order, not input order.
Err Results are ignored. When count Ok values have settled,
queued Tasks are not started and remaining running Tasks are aborted. If
fewer than count Tasks return Ok, returns the Ok values that did settle.
Sequential by default; pass a concurrency option to run more than one Task
at a time. The count uses Int1To100OrPositiveInt: pass 1 to 100 as
a literal, or a validated PositiveInt for larger values.
Example
import {
assertFalse,
assertOk,
createRun,
err,
firstN,
ok,
sleep,
type Task,
type Typed,
} from "@evolu/common";
let slowCompleted = false;
const slow: Task<string> = async (run) => {
await run.ok(sleep("10ms"));
slowCompleted = true;
return ok("slow");
};
const unavailable: Task<never, ServiceUnavailableError> = () =>
err({ type: "ServiceUnavailable" });
interface ServiceUnavailableError extends Typed<"ServiceUnavailable"> {}
const tasks = [
slow,
unavailable,
() => ok("fast-1"),
() => ok("fast-2"),
] as const;
await using run = createRun();
// Errs do not count. After two Ok values settle, the slow Task is aborted.
const result = await run(firstN(tasks, 2, { concurrency: 4 }));
assertOk(result, ["fast-1", "fast-2"]);
assertFalse(slowCompleted);