As most people know internet explorer has a maximum capacity of 2 http connections at one time, so when more than 2 ajax calls were made on a page at the same time one of the ajax requests was being forgotten, as this was an issue for one fo my clients I built this object handler, it’s using the library dojo but only for basic queries and the ajax call, you can replace these with jQuery selectors and the jQuery load function, I just thought I’d show you the principle of what I have built.
/*******************************************************************************
* This object provides testing for connections
* awl is my sites main obj
******************************************************************************/
awl.connections = new ( function() {
var maxconnections = 5;//default
if(dojo.isIE){
var maxconnections = 2;//ie default
}
var index = 0;
this.callList = {} //stored calls
this.countRunning = 0;
//public function
this.init = function(args,calltype,callcat,name,uId) {
//set up call obj
index++;
awl.connections.callList[index] = {
'args':args,
'calltype':calltype,
'callcat':callcat,
'name':name,
'uId':uId
}
//call logic
if(callcat == 'mustqueue'){
//check for other must queues, if so flag it as this call next
var queueIndex = checkIfMustQueueRunning(name, index);
if(!queueIndex) {
//no must calls running call normally
makeCall(index);
}
} else if(callcat == 'supercede'){
//check for other supercedes running
var sameIndex = checkIfSimilarRunning(name);
if(sameIndex) {
//set cancelled and cancel old supercede call
awl.connections.callList[sameIndex].cancelled = true;
awl.connections.callList[sameIndex].handle.cancel();
//now make call
makeCall(index);
} else if(checkConnections()){
makeCall(index);
}
} else if(callcat != 'cancellable' && !checkConnections()){
//check if cancellable connections available
var cIndex = checkIfCancellableRunning();
if(cIndex) {
//set cancelled and cancel old supercede call
awl.connections.callList[cIndex].cancelled = true;
awl.connections.callList[cIndex].handle.cancel();
//now make call
makeCall(index);
}
} else if(checkConnections()){
//make call
makeCall(index);
}
}
this.finalise = function(refId){
//decrement count
awl.connections.countRunning--;
//remove state indicates what to do next after removing the call, returns obj
// state 1 = make next in queue if it exists
// state 2 = make next must queue, also provides index of next must queue
// state 3 = call already made as has been cancelled, do nothing
var removeState = removeCall(refId);
//if connection was cancelled call already made, if not make call
if(removeState.state == 1){
//now check for queued calls
//get next in the queue
var nextIndex = getNextCallIndex();
if(nextIndex){
makeCall(nextIndex);
}
} else if(removeState.state == 2){
makeCall(removeState.nextIndex);
} else {
//do nothing
}
}
this.getUniqueId = function() {
// create unique id
return 'con_' + index;
}
function checkIfMustQueueRunning(name,index) {
var ma = awl.connections.callList, ind = null;
for(var x in ma){
if(ma[x].callcat == 'mustqueue' && ma[x].running && ma[x].name == name){
setNextIndex(ma[x],index);
ind = x;
}
}
return ind;
}
function setNextIndex(rObj,index){
if(rObj.nextIndex){
//already got a next index so loop until next index not set
setNextIndex(awl.connections.callList[rObj.nextIndex],index);
} else {
//set next index to run
rObj.nextIndex = index;
}
}
function checkIfCancellableRunning(n) {
var ma = awl.connections.callList, ind = null;
for(var x in ma){
if(ma[x].callcat == 'cancellable' && ma[x].running){
ind = x;
}
}
return ind;
}
function checkIfSimilarRunning(n) {
var ma = awl.connections.callList, ind = null;
for(var x in ma){
if(ma[x].name == n && ma[x].running){
ind = x;
}
}
return ind;
}
function removeCall(id){
var ma = awl.connections.callList, oState = {};
for(var x in ma){
if(ma[x].uId && ma[x].uId==id){
if(awl.connections.callList[x].cancelled){
//flag that it was cancelled
oState.state = 3;
} else if (awl.connections.callList[x].nextIndex){
oState.state = 2;
oState.nextIndex = awl.connections.callList[x].nextIndex;
} else {
oState.state = 1;
}
//remove call
delete awl.connections.callList[x];
}
}
return oState;
}
function makeCall(i){
var oCall = awl.connections.callList[i];
if(oCall && !oCall.running){
//increment count running
awl.connections.countRunning++;
if (oCall.calltype=="get"){
oCall.handle = dojo.xhrGet(oCall.args);
} else if (oCall.calltype=="post") {
oCall.handle = dojo.xhrPost(oCall.args);
}
//flag as active
oCall.running = true;
}
}
function getNextCallIndex() {
var ma = awl.connections.callList,i=null;
for(var x in ma){
//if not running or not queued to be next if the lowest index
if(!ma[x].running && !ma[x].nextIndex){
if(!i){
i=x;
} else if(x<i){
i=x;
}
}
}
return i;
}
function checkConnections() {
//console.log("count: ",awl.connections.countRunning);
if (awl.connections.countRunning < maxconnections){
return true;
} else {
return false;
}
}
/** for test only below */
this.runTest = function() {
fakeAjax();
setTimeout(function(){
fakeAjax();
},200);
setTimeout(function(){
fakeAjax();
},300);
setTimeout(function(){
fakeAjax();
},400);
setTimeout(function(){
fakeAjax();
},500);
}
function fakeAjax(t) {
var uId = awl.connections.getUniqueId(),
type = t ? t : 'mustqueue';
var xhrArgs = {
url : 'SearchLookAhead?storeId=10151&catalogId=15001&langId=44&searchTerm=bat',
handleAs : 'text',
preventCache : true,
load : function(d) {
awl.connections.finalise(uId);
console.log("fake ajax finished");
},
error : function(error) {
awl.connections.finalise(uId);
console.log("fake ajax cancelled");
}
}
//this is how to call you ajax call using the defined xhrArgs obj above
awl.connections.init(xhrArgs,'get',type,'test',uId);
}
});
Leave A Comment