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

时间:2022-11-30 03:58:24

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

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

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

我想添加一个“加载器”,它将在XAX之后显示,同时AJAX正在处理结果。

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

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

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

我试图使用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");
});

or:

要么:

$(document).ajaxStart(function() {

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

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

(delaying jquery css changes)

(延迟jquery css的变化)

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

但我遇到的问题是,任何试图延迟ajax启动时css更改的尝试最常导致延迟......然后加载出现(在ajax完成之后)。

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

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

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

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

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

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

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

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

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

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

Is there a way to time something within AJAX requests?

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

3 个解决方案

#1


8  

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

setTimeout()有一个很好的功能,你可以获得对超时的引用并取消它。

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

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

#2


4  

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

在显示#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");
});

#3


1  

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:

我最终想要一个基于元素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();
            }
      });

And the bit of relevant PHP/HTML:

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

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.

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

#1


8  

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

setTimeout()有一个很好的功能,你可以获得对超时的引用并取消它。

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

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

#2


4  

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

在显示#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");
});

#3


1  

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:

我最终想要一个基于元素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();
            }
      });

And the bit of relevant PHP/HTML:

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

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.

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