ko with asynch computed + timer
by nickkell
HTML
<script src="https://github.com/downloads/SteveSanderson/knockout/knockout-2.1.0.debug.js"></script>
<input type="number" data-bind="value: currentPage" />
<div data-bind="text: ko.toJSON($root)"></div>
JavaScript
ko.extenders.async = function(target, option) {
var asyncComputed = function(evaluator, owner) {
var result = ko.observable(),
currentDeferred;
result.loading = ko.observable(false); // Track whether we're waiting for a result
ko.computed(function() {
// Abort any in-flight evaluation to ensure we only notify with the latest value
if (currentDeferred) {
currentDeferred.reject();
}
var evaluatorResult = evaluator.call(owner);
// Cope with both asynchronous and synchronous values
if (evaluatorResult && (typeof evaluatorResult.done == "function")) { // Async
result.loading(true);
currentDeferred = $.Deferred().done(function(data) {
result(data);
}).always(function() {
result.loading(false);
});
evaluatorResult.always(currentDeferred.resolve);
} else { // Sync
result(evaluatorResult);
}
});
return result;
};
var o = asyncComputed(option.deferred, option.owner || target());
return o;
};
ko.extenders.intervalAsync = function(target, option) {
var o = ko.observable();
setInterval(function() {
ko.observable().extend({
async: option.async
}).subscribe(function(nv) {
o(nv);
});
}, option.interval || 500);
return o;
};
function VM() {
var self = this;
self.currentPage = ko.observable(1);
self.results = ko.observable().extend({
async: {
deferred: function() {
return $.post('/echo/json/', {
json: ko.toJSON(self.currentPage)
}, 'json').pipe(function(json) {
return json;
});
}
}
});
self.intervalAsync = ko.observable().extend({
...