API reference@evolu/commonTask › 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:3383

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 {
  assertOk,
  assertType,
  assertTrue,
  allSettled,
  createRun,
  err,
  ok,
  type Result,
  type Task,
  type Typed,
} from "@evolu/common";

const loadProfile: Task<string, ProfileNotFoundError> = () =>
  err({ type: "ProfileNotFound" });

interface ProfileNotFoundError extends Typed<"ProfileNotFound"> {}

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]));
assertType<
  Result<
    readonly [
      Result<string, ProfileNotFoundError>,
      Result<ReadonlyArray<string>>,
    ]
  >,
  typeof results
>();
assertOk(results, [
  { ok: false, error: { type: "ProfileNotFound" } },
  { ok: true, value: ["signed-in"] },
]);
// Unlike all, a later Task still runs after an Err.
assertTrue(activityLoaded);

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:3434

Runs a Task record and preserves its keys.

Example

import {
  assertOk,
  assertType,
  allSettled,
  createRun,
  err,
  ok,
  type Result,
  type Task,
  type Typed,
} from "@evolu/common";

interface User {
  readonly id: string;
}

const fetchUser: Task<User> = () => ok({ id: "user-1" });
const fetchProfile: Task<string, ProfileNotFoundError> = () =>
  err({ type: "ProfileNotFound" });

interface ProfileNotFoundError extends Typed<"ProfileNotFound"> {}

await using run = createRun();
const results = await run(
  allSettled({ user: fetchUser, profile: fetchProfile }),
);

assertType<
  Result<{
    readonly user: Result<User>;
    readonly profile: Result<string, ProfileNotFoundError>;
  }>,
  typeof results
>();
assertOk(results, {
  user: { ok: true, value: { id: "user-1" } },
  profile: { ok: false, error: { type: "ProfileNotFound" } },
});

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:3496

Maps an array to Tasks and preserves its shape.

Example

import {
  assertEqual,
  assertOk,
  assertType,
  allSettled,
  createRun,
  err,
  ok,
  type Result,
  type Task,
  type Typed,
} from "@evolu/common";

interface User {
  readonly id: string;
}

const loadUser =
  (id: string): Task<User, UserNotFoundError> =>
  () =>
    id === "missing" ? err({ type: "UserNotFound" }) : ok({ id });

interface UserNotFoundError extends Typed<"UserNotFound"> {}

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.
assertEqual(indexes, [0, 1]);

await using run = createRun();
const results = await run(loadUsers);
assertType<
  Result<
    readonly [Result<User, UserNotFoundError>, Result<User, UserNotFoundError>]
  >,
  typeof results
>();
assertOk(results, [
  { ok: true, value: { id: "user-1" } },
  { ok: false, error: { type: "UserNotFound" } },
]);

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:3569

Maps record values to Tasks and preserves the record's keys.

Example

import {
  assertEqual,
  assertOk,
  assertType,
  allSettled,
  createRun,
  err,
  ok,
  type Result,
  type Task,
  type Typed,
} from "@evolu/common";

interface User {
  readonly id: string;
}

const loadUser =
  (id: string): Task<User, UserNotFoundError> =>
  () =>
    id === "missing" ? err({ type: "UserNotFound" }) : ok({ id });

interface UserNotFoundError extends Typed<"UserNotFound"> {}

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.
assertEqual(roles, ["admin", "reviewer"]);

await using run = createRun();
const results = await run(loadUsersByRole);
assertType<
  Result<{
    readonly admin: Result<User, UserNotFoundError>;
    readonly reviewer: Result<User, UserNotFoundError>;
  }>,
  typeof results
>();
assertOk(results, {
  admin: { ok: true, value: { id: "user-1" } },
  reviewer: { ok: false, error: { type: "UserNotFound" } },
});