I show or hide a "Loading" indicator on my UI by binding its visibility to an observable named waiting
, which is defined like this:
// Viewmodel
var outstandingRequests = ko.observable(0);
// true if any requests are outstanding
var waiting = ko.computed(function() {
return outstandingRequests() > 0;
}.extend({ throttle: 500 });
// These are called when AJAX requests begin or end
function ajaxBegin() {
outstandingRequests(++outstandingRequests());
}
function ajaxEnd() {
outstandingRequests(--outstandingRequests());
}
<!-- View -->
<div data-bind="visible: waiting">Please wait, loading...</div>
I'm throttling the waiting
observable because I don't want the loading message to appear unless the request is taking a long time (>500ms in this case), to increase the perceived speed of the application. The problem is that once a long-running request finishes, the loading indicator doesn't disappear until an additional 500ms has passed. Instead, when the last outstanding request finishes, I want waiting
to flip to false immediately.
My first attempt at a fix involved using valueHasMutated()
, but the update is still delayed.
function ajaxEnd() {
outstandingRequests(--outstandingRequests());
// If that was the last request, we want the loading widget to disappear NOW.
outstandingRequests.valueHasMutated(); // Nope, 'waiting' still 500ms to update :(
}
How can I bypass the throttle extension and force waiting
to update immediately?