在 .each 枚举中插入“暂停”的最佳方法

sta*_*tti 5 javascript jquery

使用 jQuery '.each()' 在一组元素上的每个枚举中插入“暂停”的最佳/推荐方式是什么?

$( '.someClass' ).each( function() {
    $( this ).trigger( 'click' ); //fire some request that appends a new div on the body 
    //wait for div to be appended to the DOM.  perhaps use the pause here
    //execute code once the div has been appended 
});
Run Code Online (Sandbox Code Playgroud)

cdh*_*wie 3

从技术上讲,您不能像在代码中建模那样执行此操作,因为 JavaScript 是单线程的,并且通常在浏览器(或选项卡)UI 线程上运行 - 任何睡眠/延迟都会阻止浏览器重新绘制页面,并且还将阻止用户与页面交互。

您需要安排浏览器定期调用您的代码。像这样的事情就可以解决问题:

var objects = $.makeArray($( '.someClass' ));

var callback;

callback = function() {
    var item = objects.shift();

    // Do something with item.

    if (objects.length != 0) {
        setTimeout(callback, 5000);
    }
}

setTimeout(callback, 5000);
Run Code Online (Sandbox Code Playgroud)

一个例子

此解决方案假设您希望在最后一个项目完成处理后 5 秒内处理每个项目。这意味着:

  1. 如果您confirm()在处理每个项目时执行了某项操作,则将在用户关闭对话框后 5 秒后处理下一个项目。
  2. 总执行时间将为 (5000N + T),其中 N 是初始列表中的项目数,T 是处理每个项目所需的总时间。

您可以使用以下函数来封装此功能:

jQuery.eachWithDelay = function(sequence, delay, callback) {
    var objects = jQuery.makeArray(sequence);

    if (objects.length == 0) {
        return;
    }

    var f;

    f = function() {
        var item = objects.shift();

        if (callback(item) && objects.length != 0) {
            setTimeout(f, delay);
        }
    };

    setTimeout(f, delay);
};
Run Code Online (Sandbox Code Playgroud)

调用方式如下:

$.eachWithDelay($('.someClass'), 5000, function(item) {
    // Do something with item

    return true; // Return true to continue iterating, or false to stop.
});
Run Code Online (Sandbox Code Playgroud)

请参阅更新的小提琴