Watching Property Change and Events
A "Killer feature" of Looking Glass Engine is the ability to watch values change. You can also trigger methods upon changes to a property value. you can use this to bind an action method to a property update, or define a function to execute on property change.
Watches
By calling the "watch" method on a stream you can tell it to trigger a method of a stream upon value change, or to execute a custom function. The value of the change is passed to the watch function as an object ({value: currentValue, prev: pastValue, name: string}).
Or, if you call watchFlat, as a series of properties (value, prevValue, name).
const {ValueStream} = require('@wonderlandlabs/looking-glass-engine') ;
const stream = new ValueStream('coord');
stream.property('x', 0, 'number')
.property('y', 0, 'number')
.property('magnitude', 0, 'number')
.method('updateMagnitude', (s, {value, prev, name}) => {
console.log('updateMagnitude called; changing', name, ' from ', prev, 'to', value);
s.do.setMagnitude(Math.sqrt(s.my.x **2 + s.my.y**2));
})
.watch('x', 'updateMagnitude')
.watch('y', 'updateMagnitude')
.method('add', (stream, x, y) => {
stream.do.setX(x + stream.get('x'));
stream.do.setY(y + stream.get('y'));
}, true);
stream.subscribe(({value}) => {
const {x, y, magnitude} = value;
console.log('pt: (', x,',', y, '), magnitude: ', magnitude);
});
console.log('first change');
stream.do.setY(2);
console.log('second change');
stream.do.add(2, 2);
console.log('third change');
stream.set('x', 3);
console.log('fourth change');
stream.set('x', 3);
/**
pt: ( 0 , 0 ), magnitude: 0
first change
updateMagnitude called; changing y from 0 to 2
pt: ( 0 , 2 ), magnitude: 2
pt: ( 0 , 2 ), magnitude: 2
second change
updateMagnitude called; changing x from 0 to 2
updateMagnitude called; changing y from 2 to 4
pt: ( 2 , 4 ), magnitude: 4.47213595499958
third change
updateMagnitude called; changing x from 2 to 3
pt: ( 3 , 4 ), magnitude: 5
pt: ( 3 , 4 ), magnitude: 5
fourth change
*/Watched values are updated every time they are set, synchronously. Even if there is a transactional lock in place from a calling action.
Events
Events follow the node.js pattern of eventEmitters; a value can be emitted via a named event, and a listener can be attached to listen to the event. You can use this to trigger watchable errors, or emit a transient value that listeners can respond to. The main difference is that a method name can be passed to on(name) to route traffic to a specific listener.
An event is not related to the data that a ValueStream manages as state, or tied to any of the observables that are concerned with property updates. Like property watchers .on(eventName, target)'s target can be a function or (by name, when passed a string) a method of the ValueStream.

