nin-jin
2016-07-19
Atoms is abstration over Promises and Streams.
Atoms support:
- automatic dependency tracking
- automatic lifecycle management
Every atom known:
- His value or error
- Set of master atoms
- Set of slave atoms
Atom destroys when losing last slave atom. If master change state - slaves invalidates. Atoms need not GC.
Proposal API:
interface Atom<T> {
constructor( config : {
// callback that uses to pull value by formula (called from get() or update())
pull : ( prev : T ) => T
// callback that uses to put value to another state (called from set())
put : ( next : T , prev : T )=> T
// callback that called when atom want to destroy
reap : ()=> void
} )
/// get stored value, or pull value and store; trows error if stored error
get : ()=> T
/// push new value to atom
push : ( next : T )=> T
/// try to set value (controlled by put())
set : ( next : T )=> T
/// save error
fail : ( error : Error )=> this
/// invalidate and deferred update if atom has slaves
update : ()=> void
/// Thenable API
then<P> : ( done : ( next : T )=> P , fail : Error => P )=> Promise<P>
catch<P> : ( fail : Error => P )=> Promise<P>
/// Event Emitter API; call handler deffered after atom state changed
on : ( handle : ( next : T , prev : T )=> void )=> this
}
interface AtomStatic {
/// constructor
new<T>() : Atom<T>
/// force to cascade atoms synchronizing
sync() : void
/// atoms that have not slaves, but automatic evaluated
targets : Set<Atom<any>>
}
Usage:
var a = new Atom({ pull : prev => 1 }) // define a = 1
var b = new Atom({ pull : prev => a.get() + 1 }) // define a = b + 1
var c = new Atom({ pull : prev => a.get() + b.get() }) define c = a + b
Atom.targets.add( c ) // start auto evaluating c. c=3 now.
a.push( 2 ) // a = 2: b planned to defer update
Atom.sync() // cascade updating atoms: b = 3; c = 5
alert( c.get() ) // 5
var config = new Atom({ pull : prev => {
setTimeout( ()=> config.push({ name : 'Jin' }) , 1000 )
} })
var greeting = new Atom({ pull : prev => 'Hello, ' + config.get().name }) // waits until config defined
var alerter = new Atom( prev => alert( greeting.get() ) )
Atom.targtes.add( aleter ) // alerts "Hello, Jin" after 1 second
You can see some prototype here: https://github.com/nin-jin/pms-jin/tree/master/atom/prop
More examples here (russian): https://habrahabr.ru/post/240773/
Some theory here (russian): https://habrahabr.ru/post/235121/
Let us discuss about detailed api.