Created
November 19, 2013 04:55
-
-
Save tenntenn/7540535 to your computer and use it in GitHub Desktop.
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
var go = {}; | |
function extend(_super, sub) { | |
for (var k in _super) { | |
if (_super.hasOwnProperty(k)) { | |
sub[k] = _super[k]; | |
} | |
} | |
} | |
// subscribable | |
(function () { | |
var subscriptions = []; | |
var subscribable = { | |
subscribe: function (callback, callbackTarget) { | |
var subscription = { | |
callback: callback.bind(callbackTarget), | |
dispose: function () { | |
for (var i = 0; i < subscriptions.length; i++) { | |
if (subscriptions[i] === this) { | |
subscriptions.splice(i, 1); | |
break; | |
} | |
} | |
} | |
}; | |
subscriptions.push(subscription); | |
return subscription; | |
}, | |
notifySubscripters: function (valueToNotify) { | |
go.dependencyDetection.begin(); | |
var _subscriptions = subscriptions.slice(0); | |
for (var i = 0; i < _subscriptions.length; i++) { | |
var subscription = _subscriptions[i]; | |
subscription.callback(valueToNotify); | |
} | |
go.dependencyDetection.end(); | |
} | |
}; | |
go.subscribable = subscribable; | |
})(); | |
// observable | |
(function () { | |
var observable = function (initialValue) { | |
var lastValue = initialValue; | |
function observable() { | |
if (arguments.length > 0) { | |
// write | |
var newValue = arguments[0]; | |
if (newValue !== lastValue) { | |
lastValue = newValue; | |
observable.notifySubscripters(lastValue); | |
} | |
} else { | |
// read | |
go.dependencyDetection.registerDependency(this); | |
return lastValue; | |
} | |
} | |
extend(go.subscribable, observable); | |
return observable; | |
}; | |
go.observable = observable; | |
})(); | |
// dependencyDetection | |
(function () { | |
var frames = []; | |
var dependencyDetection = { | |
begin: function (callback) { | |
frames.push(callback && { | |
callback: callback, | |
distinctDependencies: [] | |
}); | |
}, | |
end: function () { | |
frames.pop(); | |
}, | |
registerDependency: function (subscribable) { | |
if (frames.length > 0) { | |
var topFrame = frames[frames.length - 1]; | |
if (topFrame || topFrame.distinctDependencies.indexOf(subscribable) >= 0) { | |
return; | |
} | |
topFrame.distinctDependencies.push(subscribable); | |
topFrame.callback(subscribable); | |
} | |
} | |
}; | |
go.dependencyDetection = dependencyDetection; | |
})(); | |
// dependentObservable | |
(function () { | |
var dependentObservable = function (readFunction) { | |
var lastValue; | |
var isBeingEvaluated; | |
var subscriptionsToDependencies = []; | |
function evaluateImmediate() { | |
if (isBeingEvaluated) { | |
return; | |
} | |
isBeingEvaluated = true; | |
for (var i = 0; i < subscriptionsToDependencies.length; i++) { | |
subscriptionsToDependencies[i].dispose(); | |
} | |
subscriptionsToDependencies = []; | |
go.dependencyDetection.begin(function (subscribable) { | |
subscriptionsToDependencies.push(subscribable.subscribe(evaluateImmediate)); | |
}); | |
var newValue = readFunction(); | |
if (newValue !== lastValue) { | |
lastValue = newValue; | |
dependentObservable.notifySubscripters(lastValue); | |
} | |
isBeingEvaluated = false; | |
} | |
function dependentObservable() { | |
if (arguments.length > 0) { | |
// write | |
var newValue = arguments[0]; | |
if (newValue !== lastValue) { | |
lastValue = newValue; | |
observable.notifySubscripters(lastValue); | |
} | |
} else { | |
// read | |
evaluateImmediate(); | |
go.dependencyDetection.registerDependency(this); | |
return lastValue; | |
} | |
} | |
extend(go.subscribable, dependentObservable); | |
evaluateImmediate(); | |
return dependentObservable; | |
}; | |
go.dependentObservable = dependentObservable; | |
go.computed = dependentObservable; | |
})(); | |
var a = go.observable(100); | |
var b = go.observable(200); | |
var c = go.computed(function() { | |
return a() + b(); | |
}); | |
var d = go.computed(function() { | |
return c() * 2; | |
}); | |
console.log(a(), b(), c(), d()); | |
a(200); | |
console.log(a(), b(), c(), d()); | |
b(300); | |
console.log(a(), b(), c(), d()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment