API reference › @evolu/common › Task › allSettled
Call Signature
function allSettled<TTasks>(
tasks: TTasks,
options?: TaskCollectionOptions,
): Task<
InferTasksSettled<TTasks>,
never,
ParameterIntersection<
TTasks[number] extends TTask
? TTask extends AnyTask
? (deps: InferTaskDeps<TTask>) => void
: never
: never
>
>;
Defined in: packages/common/src/Task.ts:3275
Runs all Tasks and returns every Task Result.
Unlike all, Err Results do not stop later Tasks.
With a mapping function, maps input values to Tasks before running them. The
mapper runs immediately when allSettled 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.
Sequential by default; pass a concurrency option to run more than one Task
at a time.
Similar to Promise.allSettled, but runs Tasks and returns Result values.
Example
import {
allSettled,
createRun,
err,
ok,
type Result,
type Task,
} from "@evolu/common";
interface LoadError {
readonly type: "LoadError";
}
const loadProfile: Task<string, LoadError> = () => err({ type: "LoadError" });
let activityLoaded = false;
const loadActivity: Task<ReadonlyArray<string>> = () => {
activityLoaded = true;
return ok(["signed-in"]);
};
await using run = createRun();
const results = await run(allSettled([loadProfile, loadActivity]));
expectTypeOf(results).toEqualTypeOf<
Result<readonly [Result<string, LoadError>, Result<ReadonlyArray<string>>]>
>();
expectOk(results, [
{ ok: false, error: { type: "LoadError" } },
{ ok: true, value: ["signed-in"] },
]);
// Unlike all, a later Task still runs after an Err.
expect(activityLoaded).toBe(true);
Call Signature
function allSettled<TTasks>(
tasks: TTasks,
options?: TaskCollectionOptions,
): Task<
InferTasksSettled<TTasks>,
never,
ParameterIntersection<
TTasks[keyof TTasks] extends TTask
? TTask extends AnyTask
? (deps: InferTaskDeps<TTask>) => void
: never
: never
>
>;
Defined in: packages/common/src/Task.ts:3322
Runs a Task record and preserves its keys.
Example
import {
allSettled,
createRun,
err,
ok,
type Result,
type Task,
} from "@evolu/common";
interface User {
readonly id: string;
}
interface LoadError {
readonly type: "LoadError";
}
const fetchUser: Task<User> = () => ok({ id: "user-1" });
const fetchProfile: Task<string, LoadError> = () => err({ type: "LoadError" });
await using run = createRun();
const results = await run(
allSettled({ user: fetchUser, profile: fetchProfile }),
);
expectTypeOf(results).toEqualTypeOf<
Result<{
readonly user: Result<User>;
readonly profile: Result<string, LoadError>;
}>
>();
expectOk(results, {
user: { ok: true, value: { id: "user-1" } },
profile: { ok: false, error: { type: "LoadError" } },
});
Call Signature
function allSettled<TValues, TTask>(
values: TValues,
fn: (value: TValues[number], index: number) => TTask,
options?: TaskCollectionOptions,
): Task<
{
readonly [K in string | number | symbol]: Result<
InferTaskOk<TTask>,
InferTaskErr<TTask>
>;
},
never,
ParameterIntersection<
TTask extends TTask
? TTask extends AnyTask
? (deps: InferTaskDeps<TTask>) => void
: never
: never
>
>;
Defined in: packages/common/src/Task.ts:3374
Maps an array to Tasks and preserves its shape.
Example
import {
allSettled,
createRun,
err,
ok,
type Result,
type Task,
} from "@evolu/common";
interface User {
readonly id: string;
}
interface LoadError {
readonly type: "LoadError";
}
const loadUser =
(id: string): Task<User, LoadError> =>
() =>
id === "missing" ? err({ type: "LoadError" }) : ok({ id });
const userIds = ["user-1", "missing"] as const;
const indexes: Array<number> = [];
const loadUsers = allSettled(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 results = await run(loadUsers);
expectTypeOf(results).toEqualTypeOf<
Result<readonly [Result<User, LoadError>, Result<User, LoadError>]>
>();
expectOk(results, [
{ ok: true, value: { id: "user-1" } },
{ ok: false, error: { type: "LoadError" } },
]);
Call Signature
function allSettled<TValues, TTask>(
values: TValues,
fn: (value: TValues[keyof TValues], key: keyof TValues) => TTask,
options?: TaskCollectionOptions,
): Task<
{
readonly [K in string | number | symbol]: Result<
InferTaskOk<TTask>,
InferTaskErr<TTask>
>;
},
never,
ParameterIntersection<
TTask extends TTask
? TTask extends AnyTask
? (deps: InferTaskDeps<TTask>) => void
: never
: never
>
>;
Defined in: packages/common/src/Task.ts:3442
Maps record values to Tasks and preserves its keys.
Example
import {
allSettled,
createRun,
err,
ok,
type Result,
type Task,
} from "@evolu/common";
interface User {
readonly id: string;
}
interface LoadError {
readonly type: "LoadError";
}
const loadUser =
(id: string): Task<User, LoadError> =>
() =>
id === "missing" ? err({ type: "LoadError" }) : ok({ id });
const userIdsByRole = { admin: "user-1", reviewer: "missing" } as const;
const roles: Array<keyof typeof userIdsByRole> = [];
const loadUsersByRole = allSettled(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 results = await run(loadUsersByRole);
expectTypeOf(results).toEqualTypeOf<
Result<{
readonly admin: Result<User, LoadError>;
readonly reviewer: Result<User, LoadError>;
}>
>();
expectOk(results, {
admin: { ok: true, value: { id: "user-1" } },
reviewer: { ok: false, error: { type: "LoadError" } },
});