Use JQuery promise/deferred objects to track AJAX
The JQuery library offers objects known as deferred for tracking multiple call backs, this can be used with AJAX to track cases when we only want to do something once multiple requests are complete such as re-calling the datatables update method. This also allows for us to track the completed state of a request in the ajax queue without injecting a custom completed callback into every request that is handled by the queue. Change-Id: I7d5acb6d05a5822b2de7d73678797166276ac599 Closes-Bug: 1442146
This commit is contained in:
@@ -14,38 +14,39 @@ horizon.ajax = {
|
||||
},
|
||||
// Function to add a new call to the queue.
|
||||
queue: function(opts) {
|
||||
var complete = opts.complete,
|
||||
active = horizon.ajax._active;
|
||||
|
||||
opts.complete = function () {
|
||||
var index = $.inArray(request, active);
|
||||
if (index > -1) {
|
||||
active.splice(index, 1);
|
||||
}
|
||||
horizon.ajax.next();
|
||||
if (complete) {
|
||||
complete.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
function request() {
|
||||
return $.ajax(opts);
|
||||
}
|
||||
|
||||
// Queue the request
|
||||
horizon.ajax._queue.push(request);
|
||||
|
||||
var def = $.Deferred();
|
||||
horizon.ajax._queue.push({opts: opts, deferred: def});
|
||||
// Start up the queue handler in case it's stopped.
|
||||
horizon.ajax.next();
|
||||
return def.promise();
|
||||
},
|
||||
next: function () {
|
||||
var queue = horizon.ajax._queue,
|
||||
limit = horizon.conf.ajax.queue_limit,
|
||||
request;
|
||||
var queue = horizon.ajax._queue;
|
||||
var limit = horizon.conf.ajax.queue_limit;
|
||||
|
||||
function process_queue(request) {
|
||||
return function() {
|
||||
// TODO(sambetts) Add some processing for error cases
|
||||
// such as unauthorised etc.
|
||||
var active = horizon.ajax._active;
|
||||
var index = $.inArray(request, active);
|
||||
if (index > -1) {
|
||||
active.splice(index, 1);
|
||||
}
|
||||
horizon.ajax.next();
|
||||
};
|
||||
}
|
||||
|
||||
if (queue.length && (!limit || horizon.ajax._active.length < limit)) {
|
||||
request = queue.pop();
|
||||
var item = queue.shift();
|
||||
var request = $.ajax(item.opts);
|
||||
horizon.ajax._active.push(request);
|
||||
return request();
|
||||
|
||||
// Add an always callback that processes the next part of the queue,
|
||||
// as well as success and fail callbacks that resolved/rejects
|
||||
// the deferred.
|
||||
request.always(process_queue(request));
|
||||
request.then(item.deferred.resolve, item.deferred.reject);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,30 +1,29 @@
|
||||
/* Namespace for core functionality related to DataTables. */
|
||||
horizon.datatables = {
|
||||
update: function () {
|
||||
var $rows_to_update = $('tr.status_unknown.ajax-update'),
|
||||
rows_to_update = $rows_to_update.length;
|
||||
if ( rows_to_update > 0 ) {
|
||||
var interval = $rows_to_update.attr('data-update-interval'),
|
||||
$table = $rows_to_update.closest('table'),
|
||||
submit_in_progress = $table.closest('form').attr('data-submitted'),
|
||||
decay_constant = $table.attr('decay_constant');
|
||||
var $rows_to_update = $('tr.status_unknown.ajax-update');
|
||||
var $table = $rows_to_update.closest('table');
|
||||
var interval = $rows_to_update.attr('data-update-interval');
|
||||
var decay_constant = $table.attr('decay_constant');
|
||||
var requests = [];
|
||||
|
||||
// Do not update this row if the action column is expanded or the form
|
||||
// is in the process of being submitted. If we update the row while the
|
||||
// form is still submitting any disabled action buttons would potentially
|
||||
// be enabled again, allowing for multiple form submits.
|
||||
if ($rows_to_update.find('.actions_column .btn-group.open').length ||
|
||||
submit_in_progress) {
|
||||
// Wait and try to update again in next interval instead
|
||||
setTimeout(horizon.datatables.update, interval);
|
||||
// Remove interval decay, since this will not hit server
|
||||
$table.removeAttr('decay_constant');
|
||||
return;
|
||||
}
|
||||
// Trigger the update handlers.
|
||||
$rows_to_update.each(function() {
|
||||
var $row = $(this),
|
||||
$table = $row.closest('table.datatable');
|
||||
// do nothing if there are no rows to update.
|
||||
if($rows_to_update.length <= 0) { return; }
|
||||
|
||||
// Do not update this row if the action column is expanded
|
||||
if ($rows_to_update.find('.actions_column .btn-group.open').length) {
|
||||
// Wait and try to update again in next interval instead
|
||||
setTimeout(horizon.datatables.update, interval);
|
||||
// Remove interval decay, since this will not hit server
|
||||
$table.removeAttr('decay_constant');
|
||||
return;
|
||||
}
|
||||
|
||||
$rows_to_update.each(function() {
|
||||
var $row = $(this);
|
||||
var $table = $row.closest('table.datatable');
|
||||
|
||||
requests.push(
|
||||
horizon.ajax.queue({
|
||||
url: $row.attr('data-update-url'),
|
||||
error: function (jqXHR) {
|
||||
@@ -98,26 +97,20 @@ horizon.datatables = {
|
||||
complete: function () {
|
||||
// Revalidate the button check for the updated table
|
||||
horizon.datatables.validate_button();
|
||||
rows_to_update--;
|
||||
// Schedule next poll when all the rows are updated
|
||||
if ( rows_to_update === 0 ) {
|
||||
// Set interval decay to this table, and increase if it already exist
|
||||
if(decay_constant === undefined) {
|
||||
decay_constant = 1;
|
||||
} else {
|
||||
decay_constant++;
|
||||
}
|
||||
$table.attr('decay_constant', decay_constant);
|
||||
// Poll until there are no rows in an "unknown" state on the page.
|
||||
var next_poll = interval * decay_constant;
|
||||
// Limit the interval to 30 secs
|
||||
if(next_poll > 30 * 1000) { next_poll = 30 * 1000; }
|
||||
setTimeout(horizon.datatables.update, next_poll);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
$.when.apply($, requests).always(function() {
|
||||
decay_constant = decay_constant || 0;
|
||||
decay_constant++;
|
||||
$table.attr('decay_constant', decay_constant);
|
||||
var next_poll = interval * decay_constant;
|
||||
// Limit the interval to 30 secs
|
||||
if(next_poll > 30 * 1000) { next_poll = 30 * 1000; }
|
||||
setTimeout(horizon.datatables.update, next_poll);
|
||||
});
|
||||
},
|
||||
|
||||
update_actions: function() {
|
||||
|
||||
Reference in New Issue
Block a user