在jQuery中使用deferred多个$ .each循环

时间:2015-04-18 06:16:41

标签: javascript jquery promise jquery-deferred deferred

我有三个循环,所有三个可能相互依赖,也可能不依赖于所选的页面级过滤器。总共有3个过滤器

if(filter1 is selected) {
  //runs first $.each loop and alters some of custom attr to DOM element  
}

if(filter2 is selected) {
  // Checks if filter1 was selected and are there any attr changes done by it   
  // runs second $.each loop and alters some of custom attr to DOM element   
}

filter3 .... So on

问题是我需要知道filter1中的第一个循环是否已经完成了它的任务,然后只运行第二个过滤循环,这样我就可以完全完成filter1所做的所有attr更改。所以我试图用户使用Deferred对象.Below是我的代码。

var defer = $.Deferred();
if(filter1) {
  $.each()
    .promise
    .done(function(){
      defer.resolve();
      return defer.promise()
    });
}

// same goes for filter2 and filter3

现在我想要选择filter1 [执行循环并返回承诺]或 未选择[返回承诺],然后进入同一进程的第二个过滤器。如何实现它,我怎么知道所有3个循环都已完成执行。 注意:上述过程中根本没有ajax调用。

3 个答案:

答案 0 :(得分:2)

使用$.when进行汇总和then链接。

function handleFirstFilter(){
    if(firstFilterSelected){
        var ps = [];
        $.each(elements, function(el){
            ps.push(el.animate(...).promise()); // add all the promises
        });
        return $.when.apply($, ps); // aggregate over them
    }
    return $.Deferred().resolve(); // return an empty promise resolved, nothing to do
}
// the other two filters are similar in pattern, can extract it to a function

// now execute them all with each stage waiting for the previous.
handleFirstFilter().then(handleSecondFilter).then(handleThirdFilter)

答案 1 :(得分:2)

如果您的阶段仅依赖于前一阶段的完成(而非数据),并且三个过滤处理程序的区别仅在于:

  • 特定的布尔状态,
  • 行动的元素,
  • 要应用于每个元素的asycn函数,

然后你可以写一个通用的handleFilter()函数,就像:

一样简单
function handleFilter(selected, asyncFn) {
    // return an aggregated promise or null.
    return selected ? $.when.apply(null, $.map(this, asyncFn)) : null;
}

如上所述,必须使用handleFilter().bind().apply()调用.call()才能确定this的值。

然后,您将使用handleFilter.bind()制作三个可执行文件,每个过滤器一个,并将它们传递给.then()链以进行串行执行。

$.when()
    .then(handleFilter.bind(elements_1, firstFilterSelected, asyncFn_1))
    .then(handleFilter.bind(elements_2, secondFilterSelected, asyncFn_2))
    .then(handleFilter.bind(elements_3, thirdFilterSelected, asyncFn_3))
    .then(function() {
        //everything complete
    });

每个阶段都会等待前一个阶段完成。

答案 2 :(得分:0)

  

"将一些自定义attr改为DOM元素"

不是异步操作(如超时,ajax请求或用户交互)。当循环结束时,它将被执行并完成执行。可以从第二个循环中观察所有新属性值。

您不需要承诺,只需按顺序放置同步语句,然后按顺序对其进行评估。