Ok so my solution was to use the code from Omar and enhance it for my needs:
http://www.codeproject.com/Ajax/aspnetajaxtips.asp
I have done two things. The first was to check the queue for the same method name and if it exists replace the call with the new one. This worked quite well but since 2 calls can be running i was still getting twice as many calls as i wanted and was stopping other calls from being made.
So the second thing i did was a little more code, I setup an array to store the current executing methodnames, put logic to store them and remove them when they finish. The key modification is rather then processing the next item at the top of the array [0], i go and find the next method that is not currently processing, now I had to put a bunch of loops with shortcuts so you can increase the _maxConcurrentCall but if you assumed it was only ever two then this could be refactored.
So you now simply call web services as normal and under the covers this logic ensures only one request to each webservice is running and only the most recent is then processed, plus obv you get the max 2 at one time from Omar’s original code.
var GlobalCallQueue = {
_callQueue : [], // Maintains the list of webmethods to call
_callInProgressNames : [],
// Maintains the list of webmethods names in progress by browser
_callInProgress : 0, // Number of calls currently in progress by browser
_maxConcurrentCall : 2, // Max number of calls to execute at a time
call : function(servicePath, methodName, useGet,
params, onSuccess, onFailure, userContext, timeout)
{
var queuedCall = new QueuedCall(servicePath, methodName, useGet,
params, onSuccess, onFailure, userContext, timeout);
//Check to see if there is already the same methodName in the queue.
var found=false;
for (var x=0;x<GlobalCallQueue._callQueue.length;x++)
{
if (GlobalCallQueue._callQueue[x]._methodName==methodName)
{
GlobalCallQueue._callQueue[x] = queuedCall;
found=true;
x=GlobalCallQueue._callQueue.length;
}
}
if (!found)
{
Array.add(GlobalCallQueue._callQueue,queuedCall);
}
GlobalCallQueue.run();
},
run : function()
{
/// Execute a call from the call queue
if( 0 == GlobalCallQueue._callQueue.length ) return;
if( GlobalCallQueue._callInProgress <
GlobalCallQueue._maxConcurrentCall )
{
//get first index that is not already in progess
var runIndex = 0;
for (var x=0;x<GlobalCallQueue._callQueue.length;x++)
{
var found=false;
for (var y=0;y<GlobalCallQueue._callInProgressNames.length;y++)
{
if (GlobalCallQueue._callQueue[x]._methodName==GlobalCallQueue._callInProgressNames[y])
{
found=true;
y = GlobalCallQueue._callInProgressNames.length;
}
}
if (!found)
{
runIndex = x;
x = GlobalCallQueue._callQueue.length;
}
}
GlobalCallQueue._callInProgress ++;
// Get the first call queued
var queuedCall = GlobalCallQueue._callQueue[runIndex];
Array.removeAt( GlobalCallQueue._callQueue, runIndex );
//set name in progress
Array.add(GlobalCallQueue._callInProgressNames,queuedCall._methodName);
// Call the web method
queuedCall.execute();
}
else
{
// cannot run another call. Maximum concurrent
// webservice method call in progress
}
},
callComplete : function(methodName)
{
GlobalCallQueue._callInProgress --;
//remove name in progress
for (var x=0;x<GlobalCallQueue._callInProgressNames.length;x++)
{
if (GlobalCallQueue._callInProgressNames[x]._methodName==methodName)
{
Array.removeAt( GlobalCallQueue._callInProgressNames, x );
x = GlobalCallQueue._callInProgressNames.length;
}
}
GlobalCallQueue.run();
}
};
QueuedCall = function( servicePath, methodName, useGet, params,
onSuccess, onFailure, userContext, timeout )
{
this._servicePath = servicePath;
this._methodName = methodName;
this._useGet = useGet;
this._params = params;
this._onSuccess = onSuccess;
this._onFailure = onFailure;
this._userContext = userContext;
this._timeout = timeout;
}
QueuedCall.prototype =
{
execute : function()
{
Sys.Net.WebServiceProxy.original_invoke(
this._servicePath, this._methodName, this._useGet, this._params,
Function.createDelegate(this, this.onSuccess), // Handle call complete
Function.createDelegate(this, this.onFailure), // Handle call complete
this._userContext, this._timeout );
},
onSuccess : function(result, userContext, methodName)
{
this._onSuccess(result, userContext, methodName);
GlobalCallQueue.callComplete(methodName);
},
onFailure : function(result, userContext, methodName)
{
this._onFailure(result, userContext, methodName);
GlobalCallQueue.callComplete(methodName);
}
};
Sys.Net.WebServiceProxy.original_invoke = Sys.Net.WebServiceProxy.invoke;
Sys.Net.WebServiceProxy.invoke =
function Sys$Net$WebServiceProxy$invoke(servicePath, methodName,
useGet, params, onSuccess, onFailure, userContext, timeout)
{
GlobalCallQueue.call(servicePath, methodName, useGet, params,
onSuccess, onFailure, userContext, timeout);
}