mirror of
https://github.com/ACSPRI/queXS
synced 2024-04-02 12:12:16 +00:00
237 lines
5.9 KiB
JavaScript
237 lines
5.9 KiB
JavaScript
/**
|
|
* Various processing queues, use when you want to control how multiple requests are made
|
|
* @category HTML
|
|
* @package AJAX
|
|
* @author Joshua Eichorn <josh@bluga.net>
|
|
* @copyright 2005 Joshua Eichorn
|
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
|
*/
|
|
|
|
// Single Buffer queue with interval
|
|
// works by attempting to send a request every x miliseconds
|
|
// if an item is currently in the queue when a new item is added it will be replaced
|
|
// simple queue, just processes the request immediately
|
|
// the first request starts the interval timer
|
|
function HTML_AJAX_Queue_Interval_SingleBuffer(interval,singleOutstandingRequest) {
|
|
this.interval = interval;
|
|
if (singleOutstandingRequest) {
|
|
this.singleOutstandingRequest = true;
|
|
}
|
|
}
|
|
HTML_AJAX_Queue_Interval_SingleBuffer.prototype = {
|
|
request: false,
|
|
_intervalId: false,
|
|
singleOutstandingRequest: false,
|
|
client: false,
|
|
addRequest: function(request) {
|
|
this.request = request;
|
|
},
|
|
processRequest: function() {
|
|
if (!this._intervalId) {
|
|
this.runInterval();
|
|
this.start();
|
|
}
|
|
},
|
|
start: function() {
|
|
var self = this;
|
|
this._intervalId = setInterval(function() { self.runInterval() },this.interval);
|
|
},
|
|
stop: function() {
|
|
clearInterval(this._intervalId);
|
|
},
|
|
runInterval: function() {
|
|
if (this.request) {
|
|
if (this.singleOutstandingRequest && this.client) {
|
|
this.client.abort();
|
|
}
|
|
this.client = HTML_AJAX.httpClient();
|
|
this.client.request = this.request;
|
|
this.request = false;
|
|
this.client.makeRequest();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Requests return in the same order they were called
|
|
// this helps handle high latency situations
|
|
function HTML_AJAX_Queue_Ordered() { }
|
|
HTML_AJAX_Queue_Ordered.prototype = {
|
|
request: false,
|
|
order: 0,
|
|
current: 0,
|
|
callbacks: {},
|
|
interned: {},
|
|
addRequest: function(request) {
|
|
request.order = this.order;
|
|
this.request = request;
|
|
this.callbacks[this.order] = this.request.callback;
|
|
var self = this;
|
|
this.request.callback = function(result) {
|
|
self.processCallback(result,request.order);
|
|
}
|
|
},
|
|
processRequest: function() {
|
|
var client = HTML_AJAX.httpClient();
|
|
client.request = this.request;
|
|
client.makeRequest();
|
|
this.order++;
|
|
},
|
|
requestComplete: function(request,e) {
|
|
// something when wrong with the request lets stop waiting for it
|
|
if (e) {
|
|
this.current++;
|
|
}
|
|
},
|
|
processCallback: function(result,order) {
|
|
if (order == this.current) {
|
|
this.callbacks[order](result);
|
|
this.current++;
|
|
}
|
|
else {
|
|
this.interned[order] = result;
|
|
}
|
|
while (this.interned[this.current]) {
|
|
this.callbacks[this.current](this.interned[this.current]);
|
|
this.current++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Make a single request at once, canceling and currently outstanding requests when a new one is made
|
|
function HTML_AJAX_Queue_Single() {
|
|
}
|
|
HTML_AJAX_Queue_Single.prototype = {
|
|
request: false,
|
|
client: false,
|
|
addRequest: function(request) {
|
|
this.request = request;
|
|
},
|
|
processRequest: function() {
|
|
if (this.request) {
|
|
if (this.client) {
|
|
this.client.abort();
|
|
}
|
|
this.client = HTML_AJAX.httpClient();
|
|
this.client.request = this.request;
|
|
this.request = false;
|
|
this.client.makeRequest();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Priority queue
|
|
*
|
|
* @author Arpad Ray <arpad@php.net>
|
|
*/
|
|
function HTML_AJAX_Queue_Priority_Item(item, time) {
|
|
this.item = item;
|
|
this.time = time;
|
|
}
|
|
HTML_AJAX_Queue_Priority_Item.prototype = {
|
|
compareTo: function (other) {
|
|
var ret = this.item.compareTo(other.item);
|
|
if (ret == 0) {
|
|
ret = this.time - other.time;
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
function HTML_AJAX_Queue_Priority_Simple(interval) {
|
|
this.interval = interval;
|
|
this.idleMax = 10; // keep the interval going with an empty queue for 10 intervals
|
|
this.requestTimeout = 5; // retry uncompleted requests after 5 seconds
|
|
this.checkRetryChance = 0.1; // check for uncompleted requests to retry on 10% of intervals
|
|
this._intervalId = 0;
|
|
this._requests = [];
|
|
this._removed = [];
|
|
this._len = 0;
|
|
this._removedLen = 0;
|
|
this._idle = 0;
|
|
}
|
|
HTML_AJAX_Queue_Priority_Simple.prototype = {
|
|
isEmpty: function () {
|
|
return this._len == 0;
|
|
},
|
|
addRequest: function (request) {
|
|
request = new HTML_AJAX_Queue_Priority_Item(request, new Date().getTime());
|
|
++this._len;
|
|
if (this.isEmpty()) {
|
|
this._requests[0] = request;
|
|
return;
|
|
}
|
|
for (i = 0; i < this._len - 1; i++) {
|
|
if (request.compareTo(this._requests[i]) < 0) {
|
|
this._requests.splice(i, 1, request, this._requests[i]);
|
|
return;
|
|
}
|
|
}
|
|
this._requests.push(request);
|
|
},
|
|
peek: function () {
|
|
return (this.isEmpty() ? false : this._requests[0]);
|
|
},
|
|
requestComplete: function (request) {
|
|
for (i = 0; i < this._removedLen; i++) {
|
|
if (this._removed[i].item == request) {
|
|
this._removed.splice(i, 1);
|
|
--this._removedLen;
|
|
out('removed from _removed');
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
processRequest: function() {
|
|
if (!this._intervalId) {
|
|
this._runInterval();
|
|
this._start();
|
|
}
|
|
this._idle = 0;
|
|
},
|
|
_runInterval: function() {
|
|
if (Math.random() < this.checkRetryChance) {
|
|
this._doRetries();
|
|
}
|
|
if (this.isEmpty()) {
|
|
if (++this._idle > this.idleMax) {
|
|
this._stop();
|
|
}
|
|
return;
|
|
}
|
|
var client = HTML_AJAX.httpClient();
|
|
if (!client) {
|
|
return;
|
|
}
|
|
var request = this.peek();
|
|
if (!request) {
|
|
this._requests.splice(0, 1);
|
|
return;
|
|
}
|
|
client.request = request.item;
|
|
client.makeRequest();
|
|
this._requests.splice(0, 1);
|
|
--this._len;
|
|
this._removed[this._removedLen++] = new HTML_AJAX_Queue_Priority_Item(request, new Date().getTime());
|
|
},
|
|
_doRetries: function () {
|
|
for (i = 0; i < this._removedLen; i++) {
|
|
if (this._removed[i].time + this._requestTimeout < new Date().getTime()) {
|
|
this.addRequest(request.item);
|
|
this._removed.splice(i, 1);
|
|
--this._removedLen;
|
|
return true;
|
|
}
|
|
}
|
|
},
|
|
_start: function() {
|
|
var self = this;
|
|
this._intervalId = setInterval(function() { self._runInterval() }, this.interval);
|
|
},
|
|
_stop: function() {
|
|
clearInterval(this._intervalId);
|
|
this._intervalId = 0;
|
|
}
|
|
};
|