Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/oakfang/xain

Using ES2015 proxies to simplify observation and reaction
https://github.com/oakfang/xain

Last synced: 6 days ago
JSON representation

Using ES2015 proxies to simplify observation and reaction

Awesome Lists containing this project

README

        

# xain
Using ES2015 proxies to simplify observation and reaction

## Usage

### Simple observation

```js
'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)

```js
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

```js
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

```js
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]);
```