Last active
July 23, 2016 23:52
-
-
Save WreckedAvent/7b7fe28895c9d8a376766422d045b270 to your computer and use it in GitHub Desktop.
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
import * as m from 'mithril' | |
import * as ko from 'knockout' | |
// both mithril and knockout have a concept of 'observables' | |
// mithril calls this a 'prop' for some reason or another | |
var mObs = m.prop() | |
var kObs = ko.observable() | |
// observables have a fairly simple operation - call it with nothing | |
// to get the current state, call it with something to set the state | |
mObs(25) | |
kObs(25) | |
console.log(mObs(), kObs()) // 25 25 | |
// until the rewrite, however, the mithril observables had no dependency tracking | |
// and no way to create child observables. You just had to call the observables each time | |
var first = m.prop('Jane') | |
var last = m.prop('Doe') | |
var full = () => `${first()} ${last()}` | |
console.log(full()) // Jane Doe, both first and last called | |
first('Bob') | |
console.log(full()) // Bob Doe, both first and last called | |
console.log(full()) // Bob Doe, both first and last called | |
console.log(full()) // Bob Doe, both first and last called | |
// knockout, however, has a concept of dependency tracking, and subscriptions. You can write | |
// the above code with a direct child relationship. These were called 'computed' observables | |
first = ko.observable('Jane') | |
last = ko.observable('Doe') | |
// as this is created, ko will create a subscription on these two values, and only update them as they are changed | |
full = ko.computed(() => `${first()} ${last()}`) | |
// both first and last will be called immediately as this is set up | |
console.log(full()) // Jane Doe, neither first or last were called | |
first('Bob') // changing this EAGERLY changes name to have the new value, first and last are called here | |
console.log(full()) // Bob Doe, neither first or last were called | |
console.log(full()) // Bob Doe, neither first or last were called | |
console.log(full()) // Bob Doe, neither first or last were called | |
// this is because knockout manages dependency graphs, and update sthe children as their dependencies change | |
// mithril props are just very simple getter/setter factories and not 'true' observables | |
// however, in the rewrite, this is different | |
first = m.prop('Jane') | |
last = m.prop('Doe') | |
full = m.prop.combine((f, l) => `${f()} ${l()}`, [first, last]) | |
// this behaves similarly to the knockout code, however it is quite a bit more cumbersome to set up | |
// knockout determines the dependency graphs automatically, mithril requires us to manually merge and specify them | |
// I intentionally named them 'f' and 'l' to show that they were not the same as the outer first/last props | |
console.log(full()) // Jane Doe, neither first nor last were evaluated | |
first('Bob') // full is updated eagerly here | |
console.log(full()) // Bob Doe, neither first nor last were evaluated | |
console.log(full()) // Bob Doe, neither first nor last were evaluated | |
console.log(full()) // Bob Doe, neither first nor last were evaluated | |
// this is also interesting in the context of mithril, since we can return *more* than just pure values | |
// ... we can return vdom fragments | |
var permissions = m.prop('no') | |
var permView = permissions.run(perms => m('p', `You have ${perms} permissions`)) | |
// entire apps could be expressed as this cascading dependency graph |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment