如果ajax少于X秒,如何延迟显示进度?

时间:2016-02-11 20:32:42

标签: jquery css ajax delay settimeout

我在页面上有几个AJAX调用。有些完成,其他人需要一些时间 - 所有这些都取决于点击的内容。

我想添加一个“加载器”,在AJAX处理结果的X秒后显示。

我有一台装载机在工作:

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

这个功能。

但是,当AJAX请求很快时,它会在屏幕上闪烁 ...就像在眨眼间一样。除了发生“闪烁”之外,它效果很好。因此,我试图将加载程序css更改延迟几秒钟,以便快速结果不会导致“闪烁”。

我试图使用setTimeout和jQuery队列来延迟事情...... a la:

$(document).ajaxStart(function() {

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

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

或:

$(document).ajaxStart(function() {

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

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

<子>(delaying jquery css changes

或:

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

但我遇到的问题是,任何延迟cj更改的尝试都会导致延迟... 然后负载出现(在ajax完成之后)。

所以页面加载AJAX数据然后5秒钟......加载器出现。

有没有一种好方法告诉ajaxstart()函数在执行前等待X秒?

  • 我不一定想使用像onBefore函数()之类的东西来实现这部分实际的ajax调用,主要是因为某些结果很快返回并且不需要任何进度指示器。通常情况下,进展应显示。 大多数 ajax请求在5秒内完成,只有少数可能需要10-20秒。

  • 已经将'loader'的删除添加到ajax调用中的complete function()中。只是为了确定加载器在ajax完成时消失了。但是如果在达到任何setTimeout()值之前ajax完成,那么这也会失败(然后在不应该加载时出现加载器)。

如果ajax花费X秒或更长时间,我只想要对元素进行css更改...可以这样做吗?

有没有办法在AJAX请求中计时?

3 个答案:

答案 0 :(得分:8)

setTimeout()nice feature,您可以在此处获得对超时的引用并取消它。

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

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

这可以防止超时被触发,而不是等待它,如果已经调用完成则无所事事(如雅各布的答案)。

答案 1 :(得分:4)

在显示#loader

之前,只需检查ajax是否已完成
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");
});

答案 2 :(得分:1)

对于我能够找到解决方案的好答案。

我最终想要本地化&#34; loading&#34;要基于元素ID显示的图像。全局ajaxStart()ajaxComplete()功能不会处理本地事件。所以我用超时切换到beforeSend()函数:

 $('.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();
            }
      });

相关的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; }

我不知道这是对还是错,但似乎在这里按预期工作。

如果该项目的加载时间超过几毫秒,它允许字体真棒图标出现在项目标题旁边。