happy-rusty
    Preparing search index...

    Interface OnceAsync<T>

    An async-first container which can be written to only once.

    OnceAsync<T> stores Awaited<T>, matching JavaScript's Promise flattening behavior. This means OnceAsync<Promise<number>> and OnceAsync<number> behave identically, both storing number.

    Key difference from Once<T>:

    • Once<T> with sync methods stores T as-is (including Promise values)
    • OnceAsync<T> always stores Awaited<T> (flattened value)

    1.8.0

    Once for sync-only one-time initialization

    const db = OnceAsync<Database>();

    // Initialize with async function - stores the resolved Database
    const conn = await db.getOrInit(async () => Database.connect(url));

    // Get the stored value
    console.log(db.get()); // Some(Database)
    // Fallible async initialization
    const config = OnceAsync<Config>();

    const result = await config.getOrTryInit(async () => {
    try {
    const response = await fetch('/api/config');
    return Ok(await response.json());
    } catch (e) {
    return Err(e as Error);
    }
    });
    interface OnceAsync<T> {
        "[toStringTag]": "OnceAsync";
        get(): Option<Awaited<T>>;
        getOrInit(
            fn: () => Awaited<T> | PromiseLike<Awaited<T>>,
        ): Promise<Awaited<T>>;
        getOrTryInit<E>(
            fn: () => AsyncLikeResult<Awaited<T>, E> | Result<Awaited<T>, E>,
        ): AsyncResult<Awaited<T>, E>;
        isInitialized(): boolean;
        set(value: Awaited<T>): VoidResult<Awaited<T>>;
        take(): Option<Awaited<T>>;
        toString(): string;
        tryInsert(value: Awaited<T>): Result<Awaited<T>, [Awaited<T>, Awaited<T>]>;
        wait(): Promise<Awaited<T>>;
    }

    Type Parameters

    • T

      The type parameter. The actual stored type is Awaited<T>.

    Index
    "[toStringTag]": "OnceAsync"

    The well-known symbol Symbol.toStringTag used by Object.prototype.toString(). Returns 'OnceAsync' so that Object.prototype.toString.call(once) produces '[object OnceAsync]'.

    • Gets the reference to the underlying value.

      Returns Option<Awaited<T>>

      Some(value) if initialized, None otherwise.

      const once = OnceAsync<number>();
      console.log(once.get()); // None

      await once.getOrInit(async () => 42);
      console.log(once.get()); // Some(42)
    • Gets the contents, initializing it with async fn if empty.

      If multiple calls occur concurrently, only the first one will run the initialization function. Other calls will wait for it to complete. If that in-flight attempt fails (e.g. a getOrTryInit returning Err), a waiting getOrInit caller whose own fn has not run yet retries with its own fn — matching Rust's get_or_try_init.

      Not reentrant: fn must not call getOrInit/getOrTryInit on this same OnceAsync and await the result — the outer initializer waits on the inner, which in turn waits on the outer, so neither promise ever settles (a circular wait). This mirrors Rust, where a OnceLock initializer is likewise not reentrant. A re-entrant call that does not await the result instead joins the in-flight attempt and resolves with its value.

      Parameters

      • fn: () => Awaited<T> | PromiseLike<Awaited<T>>

        A function that returns PromiseLike<Awaited<T>> or Awaited<T> to initialize.

      Returns Promise<Awaited<T>>

      A promise that resolves to the stored value (Awaited<T>).

      const db = OnceAsync<Database>();

      // Multiple concurrent calls - only one connection happens
      const [db1, db2, db3] = await Promise.all([
      db.getOrInit(() => Database.connect(url)),
      db.getOrInit(() => Database.connect(url)),
      db.getOrInit(() => Database.connect(url)),
      ]);
      // db1 === db2 === db3
    • Gets the contents, initializing it with async fn if empty. If fn returns Err, remains uninitialized.

      If multiple calls occur concurrently, only the first one will run the initialization function. Other calls will wait for it to complete; if that attempt fails, a waiting caller whose own fn has not run yet retries with its own fn.

      Not reentrant: as with getOrInit, fn must not call getOrInit/getOrTryInit on this same OnceAsync and await the result, which would wait on itself and never settle.

      Type Parameters

      • E

        The error type.

      Parameters

      • fn: () => AsyncLikeResult<Awaited<T>, E> | Result<Awaited<T>, E>

        A function that returns PromiseLike<Result<Awaited<T>, E>> or Result<Awaited<T>, E>.

      Returns AsyncResult<Awaited<T>, E>

      A promise that resolves to Ok(value) or Err(error).

      const config = OnceAsync<Config>();

      const result = await config.getOrTryInit(async () => {
      try {
      const response = await fetch('/api/config');
      return Ok(await response.json());
      } catch (e) {
      return Err(e as Error);
      }
      });
    • Returns true if initialized.

      Returns boolean

      const once = OnceAsync<number>();
      console.log(once.isInitialized()); // false

      await once.getOrInit(async () => 42);
      console.log(once.isInitialized()); // true
    • Sets the contents to value.

      If an initialization attempt (getOrInit/getOrTryInit) is currently in progress, the attempt wins: set() returns Err(value) without writing, matching Rust's OnceLock::set racing an in-flight get_or_init.

      Parameters

      • value: Awaited<T>

        The value to store.

      Returns VoidResult<Awaited<T>>

      Ok(undefined) if empty, Err(value) if already initialized or being initialized.

      const once = OnceAsync<number>();

      console.log(once.set(42)); // Ok(undefined)
      console.log(once.set(100)); // Err(100) - value returned back
      console.log(once.get()); // Some(42)
    • Takes the value out, leaving it uninitialized.

      Returns Option<Awaited<T>>

      Some(value) if initialized, None otherwise.

      const once = OnceAsync<number>();
      await once.getOrInit(async () => 42);

      console.log(once.take()); // Some(42)
      console.log(once.get()); // None - now empty
      console.log(once.take()); // None
    • Custom toString implementation.

      Returns string

      const once = OnceAsync<number>();
      console.log(once.toString()); // 'OnceAsync(<uninitialized>)'

      await once.getOrInit(async () => 42);
      console.log(once.toString()); // 'OnceAsync(42)'
    • Sets the contents to value if empty, returning a reference to the value.

      Unlike set(), this method returns the stored value on success, and returns both the current and passed values on failure.

      If an initialization attempt (getOrInit/getOrTryInit) is currently in progress, the attempt wins and Err is returned; because the current value has not been committed yet, it is reported as undefined.

      Parameters

      • value: Awaited<T>

        The value to store.

      Returns Result<Awaited<T>, [Awaited<T>, Awaited<T>]>

      Ok(value) if empty, Err([currentValue, passedValue]) if already initialized or being initialized.

      const once = OnceAsync<number>();

      // First insert succeeds, returns the stored value
      const result1 = once.tryInsert(42);
      console.log(result1.unwrap()); // 42

      // Second insert fails, returns [current, passed]
      const result2 = once.tryInsert(100);
      console.log(result2.unwrapErr()); // [42, 100]
    • Waits for the cell to be initialized, then returns the value.

      If the cell is already initialized, returns immediately. If initialization is in progress, waits for it to complete. If the cell is uninitialized and no initialization is in progress, the returned promise will resolve when another caller initializes the cell.

      Unlike an in-flight init attempt, wait() never rejects: a failed getOrTryInit leaves the cell empty and the waiter keeps waiting until a later set()/init attempt succeeds. This matches Rust's OnceLock::wait, which only returns once the cell is initialized.

      Returns Promise<Awaited<T>>

      A promise that resolves to the stored value once initialized.

      const once = OnceAsync<number>();

      // Start waiting in background
      const waitPromise = once.wait();

      // Later, initialize the value
      once.set(42);

      // waitPromise resolves with 42
      console.log(await waitPromise); // 42