Last active
September 17, 2019 21:37
-
-
Save lifeart/76db7b3124824ab49318a2c635d674c3 to your computer and use it in GitHub Desktop.
JS references
This file contains 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
const contextMap = new WeakMap(); | |
function defaultContext() { | |
return window; | |
} | |
function resolveItemAndContext(ctx, item) { | |
if (item === undefined && typeof ctx === 'string') { | |
item = ctx; | |
ctx = defaultContext(); | |
} | |
return { item, ctx }; | |
} | |
function emptyReference() { | |
return { | |
value() { | |
return undefined; | |
}, | |
validate() { return true; }, | |
update() { | |
return; | |
} | |
} | |
} | |
function referenceFor(ctx, item) { | |
if (typeof ctx !== 'object' || ctx === null) { | |
return emptyReference(); | |
} | |
if (!contextMap.has(ctx)) { | |
contextMap.set(ctx, {}); | |
} | |
const paths = item.split('.'); | |
if (paths.length > 1) { | |
return referenceFor(referenceFor(ctx, paths.shift()).value(), paths.join('.')); | |
} | |
const existingRefs = contextMap.get(ctx); | |
if (!(item in existingRefs)) { | |
const ref = { | |
ver: 0, | |
value() { | |
return ctx[item]; | |
}, | |
update(value) { | |
this.ver++; | |
ctx[item] = value; | |
return value; | |
} | |
}; | |
existingRefs[item] = ref; | |
} | |
return existingRefs[item] ; | |
} | |
function get(maybeContxt, maybeItem) { | |
const { ctx, item } = resolveItemAndContext(maybeContxt, maybeItem); | |
return referenceFor(ctx, item).value(); | |
} | |
function set(...args) { | |
if (args.length <= 1) { | |
return undefined; | |
} | |
if (args.length === 2) { | |
const { ctx, item } = resolveItemAndContext(args[0]); | |
return referenceFor(ctx, item).update(args[1]); | |
} else { | |
return referenceFor(args[0], args[1]).update(args[2]); | |
} | |
} | |
function r(maybeContxt, maybeItem) { | |
const { ctx, item } = resolveItemAndContext(maybeContxt, maybeItem); | |
return referenceFor(ctx, item); | |
} | |
r('name').value() | |
r('name').update(12); | |
get('name'); | |
set('name', 'foo'); | |
var handler = { | |
get(target, name){ | |
return get(name); | |
}, | |
set(target, name, value) { | |
return set(name, value); | |
} | |
}; | |
var globalState = new Proxy({}, handler); | |
const observersMap = new WeakMap(); | |
const observersSet = new Set(); | |
function observersFor(originalRef) { | |
return observersMap.get(originalRef); | |
} | |
function registerObserver(originalRef, obs) { | |
if (!observersMap.has(originalRef)) { | |
observersMap.set(originalRef, []); | |
} | |
observersSet.add(obs); | |
observersMap.get(originalRef).push(obs); | |
} | |
function observableRef(trackedRef, cb) { | |
const ref = { | |
validate() { | |
return trackedRef.validate(); | |
}, | |
sync() { | |
trackedRef.update(); | |
return cb(trackedRef.value()); | |
} | |
}; | |
registerObserver(trackedRef.ref, ref); | |
return ref; | |
} | |
function trackedRef(ref, maybeCb) { | |
return { | |
ver: -1, | |
computedValue: null, | |
ref, | |
validate() { | |
return this.ver === this.ref.ver; | |
}, | |
value() { | |
return this.computedValue; | |
}, | |
update() { | |
if (arguments.length === 1) { | |
this.ref.update(arguments[0]); | |
} | |
this.ver = this.ref.ver; | |
this.computedValue = this.ref.value(); | |
} | |
} | |
} | |
const observalbleRef = observableRef(trackedRef(r('name')), function(newValue){ | |
console.log('newValue'); | |
}); | |
r('name').update('12'); | |
observersFor(r('name')).filter((obs)=>!obs.validate()).forEach((obs)=>obs.sync()); | |
function subscribe(item, cb) { | |
return observableRef(trackedRef(r(item)), cb); | |
} | |
subscribe('name', (value) => { console.log('valueUpdated', value) ;}); | |
function sync() { | |
observersSet.forEach((value)=>{ | |
if (!value.validate()) { value.sync() }; | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment