Skip to main content
Subscribes to an actor ref and waits for its emitted value to satisfy a predicate, and then resolves with that value. Will throw if the desired state is not reached after an optional timeout.

Signature

function waitFor<TActorRef extends AnyActorRef>(
  actorRef: TActorRef,
  predicate: (emitted: SnapshotFrom<TActorRef>) => boolean,
  options?: Partial<WaitForOptions>
): Promise<SnapshotFrom<TActorRef>>

Parameters

actorRef
AnyActorRef
required
The actor ref to subscribe to and monitor for state changes.
predicate
(emitted: SnapshotFrom<TActorRef>) => boolean
required
A function that determines if an emitted snapshot satisfies the condition to wait for. Returns true when the desired state is reached.
options
Partial<WaitForOptions>
Optional configuration object.
timeout
number
default:"Infinity"
How long to wait (in milliseconds) before rejecting, if no emitted state satisfies the predicate.
signal
AbortSignal
An AbortSignal which stops waiting when aborted. The promise will reject with the signal’s reason.

Returns

returns
Promise<SnapshotFrom<TActorRef>>
A promise that resolves with the first emitted snapshot that satisfies the predicate. The promise rejects if:
  • The timeout is exceeded (throws an error with message "Timeout of {timeout} ms exceeded")
  • The signal is aborted (rejects with the signal’s reason)
  • The actor terminates without satisfying the predicate (throws an error with message "Actor terminated without satisfying predicate")
  • The actor emits an error

Usage

Basic usage

import { waitFor } from 'xstate';

const state = await waitFor(someService, (state) => {
  return state.hasTag('loaded');
});

state.hasTag('loaded'); // true

With timeout

import { waitFor } from 'xstate';

try {
  const state = await waitFor(
    someService,
    (state) => state.matches('success'),
    { timeout: 5000 }
  );
  console.log('Success state reached:', state);
} catch (error) {
  console.error('Timeout or error occurred:', error);
}

With AbortSignal

import { waitFor } from 'xstate';

const controller = new AbortController();

// Cancel after 3 seconds
setTimeout(() => controller.abort(), 3000);

try {
  const state = await waitFor(
    someService,
    (state) => state.matches('complete'),
    { signal: controller.signal }
  );
} catch (error) {
  console.log('Aborted or failed');
}

Waiting for specific context values

import { waitFor } from 'xstate';

const state = await waitFor(
  counterActor,
  (state) => state.context.count >= 10
);

console.log('Count reached:', state.context.count);

Notes

waitFor checks the current snapshot immediately before subscribing. If the predicate is already satisfied, it resolves immediately without waiting for future emissions.
If you provide a negative timeout value, the promise will reject immediately in development mode with a console error.
Use waitFor in tests to wait for specific states before making assertions, or in application code to coordinate asynchronous workflows.