Skip to content

Instantly share code, notes, and snippets.

@tenntenn
Created November 19, 2013 04:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tenntenn/7540535 to your computer and use it in GitHub Desktop.
Save tenntenn/7540535 to your computer and use it in GitHub Desktop.
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