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

℡╲_俬逩灬. 提交于 2019-11-30 15:34:13

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

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");
});

Thnaks to the great answers I was able to find a solution.

I ultimately wanted a localized "loading" image to show based on an element ID. The global ajaxStart() and ajaxComplete() functions don't handle local events. So I switched to the beforeSend() function with a timeout:

 $('.item').click( function (e) {
        e.preventDefault(); 
        var theID = $(this).attr('data');
        var theInfo = $('.holder#h' + theID);
        var loader = $('.waiting#w' + theID);
        $('.holder').slideUp(); //closes any open data holders
        var ajaxLoadTimeout;

        if (!$(theInfo).hasClass('opened')) {
            $(this).addClass('clicked');
            $(theInfo).addClass('opened');
            $(theInfo).html(''); //removes any existing data

        $.ajax({                                      
            url: '_core/inc/getdata.php',  
            type: 'POST',
            data: ({dataid: theID}),   
            dataType: 'html',

           //shows LOCAL loader before ajax is sent
           //but waits 3 milliseconds before doing so
          //most of the ajax calls take less than 3ms
          //without the timeOut the loader "flashes" for a milisecond
            beforeSend : function() {
                ajaxLoadTimeout = setTimeout(function() { 
                $(loader).show();
                }, 300);

            },
            success: function(data) {
                $(theInfo).html(data);

                //Hides LOCAL loader upon ajax success
                clearTimeout(ajaxLoadTimeout);
                $(loader).hide();
            },
            complete: function(){
                    $(theinfo).slideDown();
                }
              });

              } else {
                $(this).removeClass('clicked');
                $(theInfo).removeClass('opened').slideUp();
            }
      });

And the bit of relevant PHP/HTML:

echo '
<h1 class="item" data="'.$this_id.'">'.$this_title.' <span class="waiting" id="w'.$this_id.'"><i class="fa fa-refresh fa-spin fa-lg"></i></span></h1>

<section class="holder" id="h'.$this_id.'"></section>';

CSS: .waiting { discplay: none; }

I don't know that this is right or wrong, but it seems to be working as expected here.

It allows the font-awesome icon to appear next to the title of an item if that item takes more than a couple milliseconds to load.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!