A method for queuing Ajax requests

A method for queuing Ajax requests

I am using a desktop style environment. This environment can have multiple windows open, each making requests back to the server. Due to some well known issues with multiple pending Ajax requests, a queuing mechanism was deemed desirable.

First some helper classes. This one implements a simple queue processor.

PHP Code:

/*
* File: Queues.js
* Date: 11-Sep-2012
* By : Kevin L. Esteb
*
* This module provides simple queue functionality. It supports
* FIFO and LIFO based queues. By default it is in FIFO mode.
*
* The constructor can be passed the following config:
*
* config = {
* fifo: true
* };
*
* que = new Ext.ux.queue.Queues(config);
*
* que.enqueue(value);
* value = que.dequeue();
*
* Where "fifo" can be either "true" or "false". When it is false, the
* queue is in LIFO mode.
*
* ---------------------------------------------------------------------
*
* Queues.js is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Queues.js is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RemoteStorageProvider.js. If not, see
* <http://www.gnu.org/licenses/>.
*
* ---------------------------------------------------------------------
*
*/

Ext.define('Ext.ux.queue.Queues', {

queue: [],
fifo: true,

constructor: function(config) {

config = config || {};
this.initialConfig = config;

Ext.apply(this, config);

},

enqueue: function(value) {

this.queue.push(value);

},

dequeue: function() {
var value = null;

if (this.queue.length > 0) {

if (this.fifo) {

value = this.queue.pop();

} else {

value = this.queue.shift();

}

}

return value;

},

peek: function(pos) {
var value = null,
last = this.queue.length - 1;

if (this.queue.length > 1) {

if (pos < 0) {

value = this.queue[0];

} else if (pos > last) {

value = this.queue[last];

} else {

value = this.queue[pos];

}

}

return value;

},

clear: function() {

this.queue = [];

},

count: function() {

return this.queue.length;

}

});

This one implements named queues.

PHP Code:

/*
* File: Manager.js
* Date: 11-Sep-2012
* By : Kevin L. Esteb
*
* This module provides a simple queue mamanger for named queues. It is
* implemented as a singleton. Usage is a follows:
*
* qmgr = Ext.ux.queue.Manager;
*
* qmgr.createQueue('ajax', {fifo: true});
* qmgr.addItem('ajax', value);
*
* while (value = qmgr.nextItem('ajax')) {
*
* }
*
* qmgr.deleteQueue('ajax');
*
* It also exposes two events:
*
* enqueued - when an item is placed into a queue.
* dequeued - when an item is removed from a queue.
*
* Both of these events provides the name of the queue that this event
* happened on.
*
* ---------------------------------------------------------------------
*
* Manager.js is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Manager.js is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RemoteStorageProvider.js. If not, see
* <http://www.gnu.org/licenses/>.
*
* ---------------------------------------------------------------------
*
*/

This class implements an event driven dispatcher to manage the queued requests.

PHP Code:

/*
* File: Dispatcher.js
* Date: 11-Sep-2012
* By : Kevin L. Esteb
*
* This module provides a method to perform queued ajax requests. It is
* implemented as a singleton. Usage is as follows:
*
* var config = {
* pending: 2,
* queue: {
* name: 'ajax',
* fifo: false
* }
* };
*
* Ext.ux.data.Dispatcher(config).run();
*
* Everything after this is event driven.
*
* ---------------------------------------------------------------------
*
* Dispatcher.js is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dispatcher.js is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RemoteStorageProvider.js. If not, see
* <http://www.gnu.org/licenses/>.
*
* ---------------------------------------------------------------------
*
*/

Now, load order is important. The above needs to be loaded and initialized before the override to Ext.data.proxy.Ajax. I found that the only reliable way to do that is to place everything into one file or use a templating engine to include them all into one request. Since the backend is written in Perl, I can use the Template Toolkit as a preprocessor. Here is the override.

PHP Code:

/*
* Load order is important. This is the only way to ensure that these
* modules are loaded before the Ext.data.proxy.Ajax override. Otherwise
* you will get undefined name space errors.
*/

/*
* Override the default behavior of Ext.data.proxy.Ajax to use a
* named queue to control the outstanding ajax requests. The queue
* is processed in a LIFO manner. The "queue" and "fifo" values can
* be overriden by configuration.
*/