Function: watchSignal()
API / @xmachines/play-signals / watchSignal
function watchSignal<T>(signal, onValue): Cleanup;Defined in: packages/play-signals/src/watch-signal.ts:45
Subscribes to one signal, with the canonical one-shot watcher lifecycle.
The callback runs from a microtask in the queue, after the watcher drains the notifications that wait. The watcher then arms itself again, so that it misses no later update. The cleanup function is idempotent, because it accepts a watcher that is detached already.
Memory safety (Phase 29):
- The
disposedflag stops a callback after the cleanup: the microtask returns at once when the cleanup runs before the microtask fires. - The
needsEnqueueguard removes the duplicates of rapid synchronous signal changes: one batch of synchronous changes queues one microtask only. - The watcher arms again BEFORE the callback: a callback that THROWS keeps the watch, a callback that RELEASES the watch leaves no watcher attached to the signal, and a callback that WRITES the signal reaches the caller with the value that it wrote.
- The watcher arms with NO argument:
watch(signal)records the edge a second time on every emission, so the edge list of the watcher and the consumer list of the signal grow by one for each change, for the life of the watch.
A CAUTION for a callback that writes the signal that it watches: the write reaches the callback, so a callback that writes a NEW value on every call runs again for ever, and the microtask queue drains never. That is the loop of the caller, and this function bounds it not — a bound here would drop the write of a caller that repairs its state one time, which is the case that the order above exists to serve. A caller that repairs from a failure must repair to a state that succeeds, or it must stop after one attempt. A write of the SAME value ends the sequence by itself, because a signal notifies for a value that it holds already never.
The return is a Cleanup: a function, and a Disposable. A caller that keeps
the release in a field and runs it from a teardown keeps that code. A caller inside one
scope writes using and writes no teardown:
using stop = watchSignal(count, render);Type Parameters
| Type Parameter |
|---|
T |
Parameters
| Parameter | Type | Description |
|---|---|---|
signal | | State<T> | Computed<T> | The Signal.State or Signal.Computed to subscribe to. |
onValue | (value) => void | The watcher calls it with the current signal value after each change. |
Returns
The release. It removes the watcher.