API reference › @evolu/common › Task › all
Call Signature
function all<TTasks>(
tasks: TTasks,
options: AllOptions,
): Task<
void,
InferTaskErr<TTasks[number]>,
ParameterIntersection<
TTasks[number] extends TTask
? TTask extends AnyTask
? (deps: InferTaskDeps<TTask>) => void
: never
: never
>
>;
Defined in: packages/common/src/Task.ts:2982
Runs Tasks until all return Ok or one returns Err.
Returns Ok with all values when every Task returns Ok. Stops on the first
Err; remaining running Tasks are aborted. Sequential by default; pass a
concurrency option to run more than one Task at a time.
Pass { collect: false } when only collective success or failure matters.
The returned Task produces void on success and does not store the Ok
values.
With a mapping function, maps input values to Tasks before running them. The
mapper runs immediately when all is called, before the returned Task
starts. Array mappers receive (value, index). Record mappers receive
(value, key). Mapper defects happen at construction time, so keep mappers
pure and cheap.
Similar to Promise.all, but runs Tasks, returns Result values, and aborts remaining Tasks on the first Err.
Example
import { all, createRun, err, ok, type Result, type Task } from "@evolu/common";
interface User {
readonly id: string;
}
interface Post {
readonly id: string;
}
const fetchUser: Task<User> = () => ok({ id: "user-1" });
const fetchPosts: Task<ReadonlyArray<Post>> = () => ok([{ id: "post-1" }]);
await using run = createRun();
const dashboard = await run(all([fetchUser, fetchPosts]));
expectTypeOf(dashboard).toEqualTypeOf<
Result<readonly [User, ReadonlyArray<Post>]>
>();
expectOk(dashboard, [{ id: "user-1" }, [{ id: "post-1" }]]);
// Skip collecting Ok values when they aren't needed.
interface SaveUserError {
readonly type: "SaveUserError";
readonly userId: string;
}
const savedUserIds: Array<string> = [];
const saveUser =
(id: string): Task<number, SaveUserError> =>
() => {
if (id === "missing") {
return err({ type: "SaveUserError", userId: id });
}
savedUserIds.push(id);
return ok(1);
};
const saveResult = await run(
all(["user-1", "missing", "user-3"], saveUser, {
collect: false,
}),
);
expectTypeOf(saveResult).toEqualTypeOf<Result<void, SaveUserError>>();
expectErr(saveResult, {
type: "SaveUserError",
userId: "missing",
});
expect(savedUserIds).toEqual(["user-1"]);
Call Signature
function all<TTasks>(
tasks: TTasks,
options: AllOptions,
): Task<
void,
InferTaskErr<TTasks[keyof TTasks]>,
ParameterIntersection<
TTasks[keyof TTasks] extends TTask
? TTask extends AnyTask
? (deps: InferTaskDeps<TTask>) => void
: never
: never
>
>;
Defined in: packages/common/src/Task.ts:2988
Runs a Task record without collecting its Ok values.
Call Signature
function all<TTasks>(
tasks: TTasks,
options?: TaskCollectionOptions,
): Task<
InferTasksOk<TTasks>,
InferTaskErr<TTasks[number]>,
ParameterIntersection<
TTasks[number] extends TTask
? TTask extends AnyTask
? (deps: InferTaskDeps<TTask>) => void
: never
: never
>
>;
Defined in: packages/common/src/Task.ts:2993
Runs Tasks until all return Ok or one returns Err.
Returns Ok with all values when every Task returns Ok. Stops on the first
Err; remaining running Tasks are aborted. Sequential by default; pass a
concurrency option to run more than one Task at a time.
Pass { collect: false } when only collective success or failure matters.
The returned Task produces void on success and does not store the Ok
values.
With a mapping function, maps input values to Tasks before running them. The
mapper runs immediately when all is called, before the returned Task
starts. Array mappers receive (value, index). Record mappers receive
(value, key). Mapper defects happen at construction time, so keep mappers
pure and cheap.
Similar to Promise.all, but runs Tasks, returns Result values, and aborts remaining Tasks on the first Err.
Example
import { all, createRun, err, ok, type Result, type Task } from "@evolu/common";
interface User {
readonly id: string;
}
interface Post {
readonly id: string;
}
const fetchUser: Task<User> = () => ok({ id: "user-1" });
const fetchPosts: Task<ReadonlyArray<Post>> = () => ok([{ id: "post-1" }]);
await using run = createRun();
const dashboard = await run(all([fetchUser, fetchPosts]));
expectTypeOf(dashboard).toEqualTypeOf<
Result<readonly [User, ReadonlyArray<Post>]>
>();
expectOk(dashboard, [{ id: "user-1" }, [{ id: "post-1" }]]);
// Skip collecting Ok values when they aren't needed.
interface SaveUserError {
readonly type: "SaveUserError";
readonly userId: string;
}
const savedUserIds: Array<string> = [];
const saveUser =
(id: string): Task<number, SaveUserError> =>
() => {
if (id === "missing") {
return err({ type: "SaveUserError", userId: id });
}
savedUserIds.push(id);
return ok(1);
};
const saveResult = await run(
all(["user-1", "missing", "user-3"], saveUser, {
collect: false,
}),
);
expectTypeOf(saveResult).toEqualTypeOf<Result<void, SaveUserError>>();
expectErr(saveResult, {
type: "SaveUserError",
userId: "missing",
});
expect(savedUserIds).toEqual(["user-1"]);
Call Signature
function all<TTasks>(
tasks: TTasks,
options?: TaskCollectionOptions,
): Task<
InferTasksOk<TTasks>,
InferTaskErr<TTasks[keyof TTasks]>,
ParameterIntersection<
TTasks[keyof TTasks] extends TTask
? TTask extends AnyTask
? (deps: InferTaskDeps<TTask>) => void
: never
: never
>
>;
Defined in: packages/common/src/Task.ts:3039
Runs a Task record and preserves its keys.
Example
import { all, createRun, ok, type Result, type Task } from "@evolu/common";
interface User {
readonly id: string;
}
interface Post {
readonly id: string;
}
const fetchUser: Task<User> = () => ok({ id: "user-1" });
const fetchPosts: Task<ReadonlyArray<Post>> = () => ok([{ id: "post-1" }]);
await using run = createRun();
const result = await run(all({ user: fetchUser, posts: fetchPosts }));
expectTypeOf(result).toEqualTypeOf<
Result<{ readonly user: User; readonly posts: ReadonlyArray<Post> }>
>();
expectOk(result, {
user: { id: "user-1" },
posts: [{ id: "post-1" }],
});
Call Signature
function all<TValues, TTask>(
values: TValues,
fn: (value: TValues[number], index: number) => TTask,
options: AllOptions,
): Task<
void,
InferTaskErr<TTask>,
ParameterIntersection<
TTask extends TTask
? TTask extends AnyTask
? (deps: InferTaskDeps<TTask>) => void
: never
: never
>
>;
Defined in: packages/common/src/Task.ts:3086
Maps an array to Tasks and preserves its shape.
Example
import { all, createRun, ok, type Result, type Task } from "@evolu/common";
interface User {
readonly id: string;
}
const loadUser =
(id: string): Task<User> =>
() =>
ok({ id });
const userIds = ["user-1", "user-2"] as const;
const indexes: Array<number> = [];
const loadUsers = all(userIds, (id, index) => {
indexes.push(index);
return loadUser(id);
});
// Mapping is eager: it happens before the returned Task starts.
expect(indexes).toEqual([0, 1]);
await using run = createRun();
const result = await run(loadUsers);
expectTypeOf(result).toEqualTypeOf<Result<readonly [User, User]>>();
expectOk(result, [{ id: "user-1" }, { id: "user-2" }]);
Call Signature
function all<TValues, TTask>(
values: TValues,
fn: (value: TValues[keyof TValues], key: keyof TValues) => TTask,
options: AllOptions,
): Task<
void,
InferTaskErr<TTask>,
ParameterIntersection<
TTask extends TTask
? TTask extends AnyTask
? (deps: InferTaskDeps<TTask>) => void
: never
: never
>
>;
Defined in: packages/common/src/Task.ts:3096
Maps record values to Tasks without collecting their Ok values.
Call Signature
function all<TValues, TTask>(
values: TValues,
fn: (value: TValues[number], index: number) => TTask,
options?: TaskCollectionOptions,
): Task<
{ readonly [K in string | number | symbol]: InferTaskOk<TTask> },
InferTaskErr<TTask>,
ParameterIntersection<
TTask extends TTask
? TTask extends AnyTask
? (deps: InferTaskDeps<TTask>) => void
: never
: never
>
>;
Defined in: packages/common/src/Task.ts:3106
Runs Tasks until all return Ok or one returns Err.
Returns Ok with all values when every Task returns Ok. Stops on the first
Err; remaining running Tasks are aborted. Sequential by default; pass a
concurrency option to run more than one Task at a time.
Pass { collect: false } when only collective success or failure matters.
The returned Task produces void on success and does not store the Ok
values.
With a mapping function, maps input values to Tasks before running them. The
mapper runs immediately when all is called, before the returned Task
starts. Array mappers receive (value, index). Record mappers receive
(value, key). Mapper defects happen at construction time, so keep mappers
pure and cheap.
Similar to Promise.all, but runs Tasks, returns Result values, and aborts remaining Tasks on the first Err.
Example
import { all, createRun, err, ok, type Result, type Task } from "@evolu/common";
interface User {
readonly id: string;
}
interface Post {
readonly id: string;
}
const fetchUser: Task<User> = () => ok({ id: "user-1" });
const fetchPosts: Task<ReadonlyArray<Post>> = () => ok([{ id: "post-1" }]);
await using run = createRun();
const dashboard = await run(all([fetchUser, fetchPosts]));
expectTypeOf(dashboard).toEqualTypeOf<
Result<readonly [User, ReadonlyArray<Post>]>
>();
expectOk(dashboard, [{ id: "user-1" }, [{ id: "post-1" }]]);
// Skip collecting Ok values when they aren't needed.
interface SaveUserError {
readonly type: "SaveUserError";
readonly userId: string;
}
const savedUserIds: Array<string> = [];
const saveUser =
(id: string): Task<number, SaveUserError> =>
() => {
if (id === "missing") {
return err({ type: "SaveUserError", userId: id });
}
savedUserIds.push(id);
return ok(1);
};
const saveResult = await run(
all(["user-1", "missing", "user-3"], saveUser, {
collect: false,
}),
);
expectTypeOf(saveResult).toEqualTypeOf<Result<void, SaveUserError>>();
expectErr(saveResult, {
type: "SaveUserError",
userId: "missing",
});
expect(savedUserIds).toEqual(["user-1"]);
Call Signature
function all<TValues, TTask>(
values: TValues,
fn: (value: TValues[keyof TValues], key: keyof TValues) => TTask,
options?: TaskCollectionOptions,
): Task<
{ readonly [K in string | number | symbol]: InferTaskOk<TTask> },
InferTaskErr<TTask>,
ParameterIntersection<
TTask extends TTask
? TTask extends AnyTask
? (deps: InferTaskDeps<TTask>) => void
: never
: never
>
>;
Defined in: packages/common/src/Task.ts:3165
Maps record values to Tasks and preserves its keys.
Example
import { all, createRun, ok, type Result, type Task } from "@evolu/common";
interface User {
readonly id: string;
}
const loadUser =
(id: string): Task<User> =>
() =>
ok({ id });
const userIdsByRole = {
admin: "user-1",
reviewer: "user-2",
} as const;
const roles: Array<keyof typeof userIdsByRole> = [];
const loadUsersByRole = all(userIdsByRole, (id, role) => {
roles.push(role);
return loadUser(id);
});
// Mapping is eager: it happens before the returned Task starts.
expect(roles).toEqual(["admin", "reviewer"]);
await using run = createRun();
const result = await run(loadUsersByRole);
expectTypeOf(result).toEqualTypeOf<
Result<{ readonly admin: User; readonly reviewer: User }>
>();
expectOk(result, {
admin: { id: "user-1" },
reviewer: { id: "user-2" },
});