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
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.
Optional configuration object.How long to wait (in milliseconds) before rejecting, if no emitted state satisfies the predicate.
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.