Search code examples
jquerycssajaxdelaysettimeout

How to delay showing of progress if ajax takes less than X seconds?


I've got a few AJAX calls on a page. Some complete instantaneously, others take a few moments -- all depending upon what is clicked.

I want to add a "loader" that will display after X seconds while AJAX is working on results.

I've got a loader working:

   $(document).ajaxStart(function() {
        $("#loader").css("display","block");
    }).ajaxSuccess(function() {
        $("#loader").css("display","none");
    });

This functions.

However, it flashes on screen when the AJAX request is fast... like in the blink of an eye. Other than the "blinking" which occurs, it works great. So, I'm trying to delay the loader css change for a few seconds so that rapid results don't result in the "blink".

I've attempted to use setTimeout and the jQuery queue to delay things.. a la:

$(document).ajaxStart(function() {

    $("#loader").queue(function(){
        $(this).delay(5000);
        $(this).css("display","block");
        $(this).dequeue();
    });

}).ajaxSuccess(function() {
    $("#loader").css("display","none");
});

or:

$(document).ajaxStart(function() {

    setTimeout(function() { 
        $("#loader").css("display","block");
    }, 5000);

}).ajaxSuccess(function() {
    $("#loader").css("display","none");
});

(delaying jquery css changes)

or:

$(document).ajaxStart(function() {
    $("#loader").delay(5000).css("display","block")
}).ajaxSuccess(function() {
    $("#loader").css("display","none");
});

But the problem I'm running into is that any attempt to delay the css change on ajax start most often results in a delay... then the load appears (after ajax is done).

So the page loads the AJAX data then 5 seconds later... the loader appears.

Is there a good way to tell the ajaxstart() function to wait X seconds before executing?

  • I don't necessarily want to make this part of the actual ajax calls using something like the onBefore function(), primarily because some result are returned very quickly and don't need any progress indicator. More often than not.. the progress should not be shown. Most ajax requests are completed in under 5 seconds, there are only a handful that may take 10-20 seconds.

  • I have added the removal of the 'loader' to the complete function() in the ajax calls. Just to be certain the loader goes away when ajax is done. But this also fails if ajax is complete before any setTimeout() value is reached (and then the loader appears afterwards when it shouldn't).

I just want a css change on an element if the ajax is taking X seconds or more... can that be done?

Is there a way to time something within AJAX requests?


Solution

  • setTimeout() has this nice feature where you can get a reference to the timeout and cancel it.

    var ajaxLoadTimeout;
    $(document).ajaxStart(function() {
        ajaxLoadTimeout = setTimeout(function() { 
            $("#loader").css("display","block");
        }, 5000);
    
    }).ajaxSuccess(function() {
        clearTimeout(ajaxLoadTimeout);
        $("#loader").css("display","none");
    });
    

    This prevents the timeout from ever firing, rather than waiting for it and doing nothing if complete has been called (as in Jacob's answer).