MwithScope
Bun

method

async_hooks.AsyncLocalStorage.withScope

store: T

Creates a disposable scope that enters the given store and automatically restores the previous store value when the scope is disposed. This method is designed to work with JavaScript's explicit resource management (using syntax).

Example:

import { AsyncLocalStorage } from 'node:async_hooks';

const asyncLocalStorage = new AsyncLocalStorage();

{
  using _ = asyncLocalStorage.withScope('my-store');
  console.log(asyncLocalStorage.getStore()); // Prints: my-store
}

console.log(asyncLocalStorage.getStore()); // Prints: undefined

The withScope() method is particularly useful for managing context in synchronous code where you want to ensure the previous store value is restored when exiting a block, even if an error is thrown.

import { AsyncLocalStorage } from 'node:async_hooks';

const asyncLocalStorage = new AsyncLocalStorage();

try {
  using _ = asyncLocalStorage.withScope('my-store');
  console.log(asyncLocalStorage.getStore()); // Prints: my-store
  throw new Error('test');
} catch (e) {
  // Store is automatically restored even after error
  console.log(asyncLocalStorage.getStore()); // Prints: undefined
}

Important: When using withScope() in async functions before the first await, be aware that the scope change will affect the caller's context. The synchronous portion of an async function (before the first await) runs immediately when called, and when it reaches the first await, it returns the promise to the caller. At that point, the scope change becomes visible in the caller's context and will persist in subsequent synchronous code until something else changes the scope value. For async operations, prefer using run() which properly isolates context across async boundaries.

import { AsyncLocalStorage } from 'node:async_hooks';

const asyncLocalStorage = new AsyncLocalStorage();

async function example() {
  using _ = asyncLocalStorage.withScope('my-store');
  console.log(asyncLocalStorage.getStore()); // Prints: my-store
  await someAsyncOperation(); // Function pauses here and returns promise
  console.log(asyncLocalStorage.getStore()); // Prints: my-store
}

// Calling without await
example(); // Synchronous portion runs, then pauses at first await
// After the promise is returned, the scope 'my-store' is now active in caller!
console.log(asyncLocalStorage.getStore()); // Prints: my-store (unexpected!)

Referenced types

interface RunScope

A disposable scope returned by asyncLocalStorage.withScope() that automatically restores the previous store value when disposed. This class implements the Explicit Resource Management protocol and is designed to work with JavaScript's using syntax.

The scope automatically restores the previous store value when the using block exits, whether through normal completion or by throwing an error.

  • dispose(): void;

    Explicitly ends the scope and restores the previous store value. This method is idempotent: calling it multiple times has the same effect as calling it once.

    The [Symbol.dispose]() method defers to dispose().

    If withScope() is called without the using keyword, dispose() must be called manually to restore the previous store value. Forgetting to call dispose() will cause the store value to persist for the remainder of the current execution context:

    import { AsyncLocalStorage } from 'node:async_hooks';
    
    const storage = new AsyncLocalStorage();
    
    // Without using, the scope must be disposed manually
    const scope = storage.withScope('my-store');
    // storage.getStore() === 'my-store' here
    
    scope.dispose(); // Restore previous value
    // storage.getStore() === undefined here