09
Signals push discrete changes to anyone listening
A scroll position or a pointer location changes only when an event happens. A signal carries those changes: it is plural and temporal like a stream, but it is broadcast, has any number of producers and consumers, and gives no guarantee of continuity. An observer sees whatever was pushed while it was subscribed, and nothing else.
The discrete event pusher is a Signal. … Signals do not support pressure. Just as yield does not return a promise, the callback you give to forEach does not accept a promise. A signal can only push.
Signal generator · move your pointer
in.yield(…) returned —Move the pointer here to push values
pushed 0 · ≤ 13/sobserver 1
received 0
last —
Same values, written into a stream
unicast · buffered · pressuredA stream would buffer all values produced until the consumer arrives. Each in.yield returns a promise for an acknowledgement that is still pending.
pushed to signal
0
buffered in stream
0
The interface
// The getter side is an observable: forEach subscribes to pushes.
signal.out.forEach(function (value, time, signal) {
console.log(value);
});
// The setter side is a signal generator. Unlike a stream writer,
// yield does not return a promise. Nobody can push back.
signal.in.yield(10);
// Observables also implement next: poll the most recent value,
// as if the signal were a behavior.
signal.out.next(); // { value: 10, done: false }A signal with no generator
Not every observable is paired with a signal generator. A clock emits the current time at a period and offset. Ours is only active while someone observes it: the last unsubscribe clears its timer.
var tick = new Clock({period: 1000});
var tock = new Clock({period: 1000, offset: 500});
tick.forEach(function (time) {
console.log("tick", time);
});
tock.forEach(function (time) {
console.log("tock", time);
});Clock: an observable with no generator
tick:
new Clock({period: 1000}) ○ idle — nobody is lookingtock: new Clock({period: 1000, offset: 500}) ○ idle — nobody is looking- why it matters
in.yieldreturnsundefined. With no acknowledgement there is no back pressure: the producer never waits, so it can never be slowed down by a slow observer. Slow observers simply miss or skip states. - why it mattersSignals are broadcast. Observers come and go without affecting the producer or each other. A late subscriber starts from now; a stream would have buffered every value until its single reader arrived.
- why it mattersBecause the meaning of the data is “the latest state”, dropping intermediate values is correct, not lossy. That is the contract that lets signals avoid over-commitment without pressure.