xain
v1.0.5
Published
Using ES2015 proxies to simplify observation and reaction
Downloads
7
Maintainers
Readme
xain
Using ES2015 proxies to simplify observation and reaction
Usage
Simple observation
'use strict';
const {observable, observe} = require('xian');
const o = observable({
foo: 1
});
let count = 0;
const unobserve = observe(o, (prop, newValue, oldValue) => count += 1); // returns a funtion that, when called, stops the observation
// count == 0
o.foo = 1;
// count == 0
o.foo = 2;
o.foo = 2;
// count == 1
o.foo = 1;
// count == 2
unobserve(); // stop the observer
o.foo = 5;
o.foo = 6;
o.foo = 7;
// count == 2
Batched observation
(Use when you make several changes and you want to get the diff, if it exists, between the first and last changes on this tick)
const o = observable({
foo: 1
}, true); // notice the `true` parameter indicating it is batched
let count = 0;
observe(o, () => count += 1);
// count == 0
o.foo = 0;
// count == 0
o.foo = 2;
o.foo = 2;
// count == 0
process.nextTick(() => {
// count == 1, and oldValue will be 1 and newValue will be 2, skipping the 0 in between
});
Reactive links
const x = require('xian');
const o = x.observable({
x: 3,
y: 6
});
let counter = 0;
const r = x.reactive({ // note: every reactive object is also `observable`, and thus can be passed to the `observe` function.
x: x.pipe(o, 'x'), // pipe changes through
y: x.pipe(o, 'y'),
z: x.link(o, ({x, y}) => { // link changes of dependencies into a new value
counter += 1;
return x + y;
})
});
t.is(r.x, 3);
t.is(r.y, 6);
t.is(r.z, 9);
t.is(counter, 1);
o.x = 3;
t.is(r.x, 3);
t.is(r.y, 6);
t.is(r.z, 9);
t.is(counter, 1);
o.x = 5;
t.is(r.x, 5);
t.is(r.y, 6);
t.is(r.z, 11);
t.is(counter, 2);
Note: a link
function must always get
every single dependency every time it runs.
The easiest way is to destructure the observable (the actual argument passed to the link function)
into the properties the link depends upon.
Observable streams
const x = require('xain');
const o = x.observable({
x: 3,
y: 6
});
const str = x.stream(o)
.filter(key => key === 'x')
.map((key, nval, oval) => oval)
.reduce((acc, val) => acc + val, 0);
const expected = [3, 4, 2];
let actual = [];
x.observe(str, v => actual.push(v));
o.x = 1;
o.x = -2;
o.x = 5;
t.is(expected[0], actual[0]);
t.is(expected[1], actual[1]);
t.is(expected[2], actual[2]);