Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 796
Scott Avatar asked Feb 11 '16 20:02

Scott


2 Answers

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).

like image 136
Draco18s no longer trusts SE Avatar answered Oct 13 '22 10:10

Draco18s no longer trusts SE


Just check if the ajax has completed before showing the #loader:

var ajaxDone; //create a global variable called ajaxDone
$(document).ajaxStart(function() {
    ajaxDone = false; //by default, set the ajax as not completed each time the ajax request is sent
    setTimeout(function() { 
        if(!ajaxDone) $("#loader").css("display","block");//checks if the ajax has finished yet before displaying #loader
    }, 5000);

}).ajaxSuccess(function() {
    ajaxDone=true;//When the ajax request finishes, it sets ajaxDone to true
    $("#loader").css("display","none");
});
like image 42
Jacob Gray Avatar answered Oct 13 '22 09:10

Jacob Gray