Skip to content

Instantly share code, notes, and snippets.

@begedin
Last active August 29, 2015 14:05
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 begedin/cc02fb31973fa7368430 to your computer and use it in GitHub Desktop.
Save begedin/cc02fb31973fa7368430 to your computer and use it in GitHub Desktop.
/// <summary>
/// A knockout computed observable that supports async data.
/// To use it, set a function that returns a deferred object, for instance, an AJAX call as the parameter.
/// While using AJAX, if server data isn't in proper format, you can use $.ajax().pipe() to map it correctly.
/// http://api.jquery.com/deferred.pipe/
///
/// There are two helper observables added to the asyncComputed
/// .inProgress returns true if data is not yet loaded (is currently being loaded)
/// .loaded is the opposite and returns true if data has been loaded
/// </summary>
/// <param name="evaluator">deferred (or regular) function</param>
/// <param name="owner">what the 'this' of the function will be set to</param>
/// <returns type="deferred">null while deferred isn't resolved, result after deferred is resolved.</returns>
ko.asyncComputed = function (evaluator, owner) {
var result = ko.observable(), currentDeferred;
result.inProgress = ko.observable(false); // Track whether we're waiting for a result
result.loaded = ko.computed(function () { return !result.inProgress(); }); // Helper to track if data is loaded.
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.inProgress(true);
currentDeferred = $.Deferred().done(function (data) {
result.inProgress(false);
result(data);
});
evaluatorResult.done(currentDeferred.resolve);
} else // Sync
result(evaluatorResult);
});
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment