setTimeout不会延迟$ .each中的函数调用

时间:2017-07-21 08:57:50

标签: javascript jquery ajax get settimeout

我的网站上有几个div,我想逐个更新。为了不一次向200多个请求发送垃圾邮件,我希望每个请求延迟1次。

我尝试了什么:

var $tourBox = $('.tour-box');
$tourBox.each(function () {
    var $box = $(this);
    setTimeout(function () {
        getUpdate($box);
    }, 1000);
});

更新功能:

function getUpdate($box) {

    var $so = $box.attr('data-so');
    var $url = $('#ajax-route-object-status').val();
    $.get($url, {
        so: $so
    }).success(function (data) {
        var $bg = 'bg-gray';
        if (data.extra.isStarted === true && data.extra.isFinished === false) {
            $bg = 'bg-orange'
        }
        if (data.extra.isStarted === true && data.extra.isFinished === true) {
            $bg = 'bg-green'
        }
        if (data.extra.isLate === true && data.extra.isFinished === false) {
            $bg = 'bg-red'
        }
        $box.removeClass('bg-gray').removeClass('bg-green').removeClass('bg-orange').removeClass('bg-red').addClass($bg);
    });
}

在Chrome Dev中 - >网络它显示所有已加载为待处理,然后逐个加载它们,但没有延迟:

ChromeDevScreenshot

正如您在3907和3940之间看到的那样,只有半秒的延迟。即使我的超时时间为5000,这也不会改变。

3 个答案:

答案 0 :(得分:2)

早在2008年,我写了a slowEach() plugin for jQuery来做你正在寻找的事情。它基本上是$.each()$(...).each()的替代品,它需要一个时间间隔,因此调用每个元素的延迟时间为回调:

jQuery.slowEach = function( array, interval, callback ) {
    if( ! array.length ) return;
    var i = 0;
    next();
    function next() {
        if( callback.call( array[i], i, array[i] ) !== false ) {
            if( ++i < array.length ) {
                setTimeout( next, interval );
            }
        }
    }
};

jQuery.fn.slowEach = function( interval, callback ) {
    jQuery.slowEach( this, interval, callback );
};

使用该代码,您可以执行以下操作:

$('.tour-box').slowEach( 1000, function() {
    getUpdate( $(this) );
});

有关此代码的一点需要注意的是,它一次只使用一个计时器,而不是进行数百次setTimeout()次调用以同时启动多个计时器。这使得系统资源变得更加容易。

答案 1 :(得分:1)

您的每个人都会立即呼叫所有超时。在每次呼叫之间不等待一秒钟。因此,您有数千个被安排在一秒钟后调用getUpdate($box);的对象。

您可以做的是在每次迭代中增加超时。

var $tourBox = $('.tour-box');
var delay = 1000;
$tourBox.each(function () {
    var $box = $(this);
    setTimeout(function () {
        getUpdate($box);
    }, delay);
    delay += 1000;
});

这将导致您的第一次超时在1秒后被触发,而您的第二次超时将在两秒后被激发,等等。

答案 2 :(得分:1)

逐个调用可能是另一种避免垃圾邮件之类的请求的解决方案。 在这种情况下,这可能是一个解决方案:

$(document).ready(function(){

    var $tourBox = $('.tour-box'),
        curIndex = 0,
        totalBox = $tourBox.length,
        url = $('#ajax-route-object-status').val(),


    function getUpdate(){

        var $box = $tourBox.get( curIndex );

        if ( typeof $box === 'undefined'){
            // No more box to process
            return; // exit
        }

        var $so = $box.attr('data-so');

        $.get($url, {
            so: $so
        }).success(function (data) {
            var $bg = 'bg-gray';
            if (data.extra.isStarted === true && data.extra.isFinished === false) {
                $bg = 'bg-orange'
            }
            if (data.extra.isStarted === true && data.extra.isFinished === true) {
                $bg = 'bg-green'
            }
            if (data.extra.isLate === true && data.extra.isFinished === false) {
                $bg = 'bg-red'
            }
            $box.removeClass('bg-gray').removeClass('bg-green').removeClass('bg-orange').removeClass('bg-red').addClass($bg);
        }).always(function(){

            // Increment index to process
            curIndex++;

            // Finished either with success or failed
            // Proceed with next
            getUpdate();
        });       
    }
});