仅在.each()完成后继续执行

时间:2012-01-28 08:38:58

标签: jquery

我正在寻找一种只在.each()完成执行后调用函数的方法。在下面的示例中,如何确保在 postPreparation()完成后$('.element').each()立即运行

$('.element').each(function() {
  /** 
   * 'prepareLayer()' is a complex function that takes a while to complete and,
   *  as in this construct, needs to be invoked for each matched element. Basically,
   * 'prepareLayer()' adds a lot of new HTML elements to the page.
   */   
  prepareLayer();
});

/**
 * Ideally, this should immediately run _after_ the above function completes
 * i.e. after each '.element' finishes running prepareLayer().
 *
 * 'postPreparation()' needs to attach some event handlers for the new HTML elements
 * created in 'prepareLayer()'.
 */
postPreparation();

从技术上讲,我正在寻找一种方法来为.each()调用回调函数。

注意:我刚刚在上面的示例中确认postPreparation()仅在.each()完成后才会执行。问题是我的prepareLayer()使用AJAX构建新的HTML元素,因此each()首先返回。正如@Alnitak所建议的那样,异步AJAX请求不会阻止.each()过早返回。

3 个答案:

答案 0 :(得分:9)

除非prepareLayer()正在做异步(例如AJAX或动画),否则在prepareLayer()完成之前,循环中的每次传递都无法终止,并且您的代码已经完成了您想要的任务。

FWIW,如果您现有的.each循环中没有其他操作或参数,您实际上只需要写这个:

$('.element').each(prepareLayer);

即。不需要额外的匿名函数包装器。

另一方面,如果它正在执行异步操作,请使用延迟对象:

var def = [];
$('.element').each(function() {
    // have prepareLayer return a _promise_ to return
    def.push(prepareLayer());
});

function prepareLayer() {
    var jqxhr = $.get(..., function() {
        // do stuff with content
    });
    return jqxhr;
}

// use "when" to call "postPreparation" once every
// promise has been resolved
$.when.apply($, def).done(postPreparation);

答案 1 :(得分:0)

我会将对postPreperation的调用包装成某种反对象。

例如:

function createEvent(numOfSignals, callback) {
    var _event = {};

    _event.signal = function() {
        if(numOfSignals > 1) {
            numOfSignals--;
        }
        else {
            callback();
        }
    };

    return _event;
}

var event = createEvent(numOfPreperations, postPreperation);

然后在prepareLayer内,我会打电话给event.signal()。如果numOfSignals为1,则会立即调用postPreperation

你会想要改进这一点,但基本的想法应该有效。您可以查看该想法的示例here

答案 2 :(得分:0)

使用jquery承诺:

$('.element').promise().done(function() {
    postPreparation();
});