Skip to content

Instantly share code, notes, and snippets.

@Terrance
Created April 10, 2016 14:37
Show Gist options
  • Save Terrance/158a4c436baa64c4324803467844b00f to your computer and use it in GitHub Desktop.
Save Terrance/158a4c436baa64c4324803467844b00f to your computer and use it in GitHub Desktop.
Limit concurrent jQuery ajax requests to at most 3 at a time, and queue the rest.
var ajaxReqs = 0;
var ajaxQueue = [];
var ajaxActive = 0;
var ajaxMaxConc = 3;
function addAjax(obj) {
ajaxReqs++;
var oldSuccess = obj.success;
var oldError = obj.error;
var callback = function() {
ajaxReqs--;
if (ajaxActive === ajaxMaxConc) {
$.ajax(ajaxQueue.shift());
} else {
ajaxActive--;
}
}
obj.success = function(resp, xhr, status) {
callback();
if (oldSuccess) oldSuccess(resp, xhr, status);
};
obj.error = function(xhr, status, error) {
callback();
if (oldError) oldError(xhr, status, error);
};
if (ajaxActive === ajaxMaxConc) {
ajaxQueue.push(obj);
} else {
ajaxActive++;
$.ajax(obj);
}
}
@zrowe
Copy link

zrowe commented Feb 11, 2018

Thanks mate. Very helpful in time of need.

@waikchiu5
Copy link

waikchiu5 commented Jul 9, 2018

Hi all, anyone can explain these code for what propose?

if (oldSuccess) oldSuccess(resp, xhr, status);
if (oldError) oldError(xhr, status, error);

or how can I use addAjax()?

@vlakoff
Copy link

vlakoff commented Aug 25, 2018

These lines are for executing the success/error callbacks you provided.

Sample use of this gist:

addAjax({
    'url': 'http://example.org/'
    'method': 'POST', // default 'GET'
    'data': {'foo': 'bar', 'baz': 'qux'}
    'success': function () { console.log('success'); },
    'error': function () { console.log('error'); },
});

That's it. Actually it's just the same as $.ajax().

Much simplicity. wow.

@dzikowskipl
Copy link

I think there is a error in code.
In this line
if (ajaxActive === ajaxMaxConc)
should be check queue is empty
I changed to
if (ajaxActive === ajaxMaxConc && ajaxQueue>0)
And works better

@Mattie112
Copy link

(yes a reply to an old post, perhaps someone can use it in the future).

The fix mentioned also does not work for my. The original one fires more requests then I add and no longer works when I re-add at a later moment. The fix only does a single "batch" then stops.

For me it works like this:

    function addAjax(obj) {
        ajaxReqs++;
        const originalSuccessCallback = obj.success;
        const originalErrorCallback = obj.error;
        const callback = function () {
            ajaxReqs--;
            ajaxActive--;

            if (ajaxQueue.length > 0 && ajaxActive < ajaxMaxConc) {
                ajaxActive++;
                $.ajax(ajaxQueue.shift());
            } else {
                ajaxActive--;
            }
        }

        obj.success = function (resp, xhr, status) {
            callback();
            if (originalSuccessCallback) originalSuccessCallback(resp, xhr, status);
        };
        obj.error = function (xhr, status, error) {
            callback();
            if (originalErrorCallback) originalErrorCallback(xhr, status, error);
        };

        if (ajaxActive === ajaxMaxConc) {
            ajaxQueue.push(obj);
        } else {
            ajaxActive++;
            $.ajax(obj);
        }
    }

@vlakoff
Copy link

vlakoff commented Sep 21, 2023

  • The mistake in the original code is that it doesn't check if ajaxQueue still contains elements. If at some point ajaxQueue gets empty, the code ends up with a (harmless) no-op $.ajax(undefined), and importantly, ajaxActive isn't decremented, which leads to various issues.
  • Your fixed code has a mistake, there is an extraneous ajaxActive--;. You may either:
    • Remove the "else" branch having the ajaxActive--;
    • Remove the first ajaxActive--;, and the ajaxActive < ajaxMaxConc and the ajaxActive++; (when callback() triggers a new request, the number of active requests stays the same)
  • ajaxActive cannot exceed ajaxMaxConc, and this is ensured when addAjax() is called. Therefore it is irrelevant to check it in callback().
  • Btw, notice the ajaxReqs variable is useless.

Considering the above points, I ended up with the following code for callback():

    var callback = function () {
        if (ajaxQueue.length > 0) {
            $.ajax(ajaxQueue.shift());
        } else {
            ajaxActive--;
        }
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment