Last active
April 26, 2018 00:06
-
-
Save wafna/dc50d9180ba62db4ffc8ac3be11edf3b to your computer and use it in GitHub Desktop.
Proxy mutable state with notifications and transformations.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
MVar is a facility for data flow among components and APIs. | |
*/ | |
const assertFunction = (f, msg) => { | |
if (typeof f !== 'function') | |
throw new Error('Function required: ' + msg); | |
}; | |
/** | |
* Generically produces a new MVar chained after the given MVar. | |
* @param m The given MVar. | |
* @param f The subscribing function. | |
* @returns {*} An MVar object. | |
* @private | |
*/ | |
const _after = (m, f) => { | |
assertFunction(f, ''); | |
const n = { | |
take: m.take, | |
put: v => { | |
m.put(v); | |
f(v); | |
return n; | |
}, | |
before: f => _before(n, f), | |
after: f => _after(n, f) | |
}; | |
return n; | |
}; | |
/** | |
* Generically produces a new MVar chained before the given MVar. | |
* @param m The given MVar. | |
* @param f The transforming function. | |
* @returns {*} An MVar object. | |
* @private | |
*/ | |
const _before = (m, f) => { | |
assertFunction(f); | |
const n = { | |
take: m.take, | |
put: v => { | |
m.put(f(v)); | |
return n; | |
}, | |
before: f => _before(n, f), | |
after: f => _after(n, f) | |
}; | |
return n; | |
}; | |
/** | |
* Creates an object that encapsulates a mutable value. | |
* This is used to hook data update notifications, transform data from other sources, and proxy | |
* data collection to other components, typically down the hierarchy. | |
* Undefined values are forbidden. | |
*/ | |
export const MVar = value => { | |
if (value === undefined) | |
throw new Error('Undefined values are forbidden.'); | |
const m = { | |
take: () => value, | |
put: v => { | |
if (v === undefined) | |
throw new Error('Undefined values are forbidden.'); | |
value = v; | |
return m; | |
}, | |
/** | |
* Create a new MVar that executes function f after the value is set. | |
* Typically, f redraws a component. | |
* @param f Takes the incoming value. | |
*/ | |
after: f => _after(m, f), | |
/** | |
* Creates a new MVar that maps new values through f before setting. | |
* Useful to coerce data, like ids from select options. | |
* @param f | |
*/ | |
before: f => _before(m, f), | |
}; | |
return m; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment