使用嵌套的jQuery $ .when时,异步处理会产生意外的结果

时间:2012-05-26 22:13:57

标签: jquery asynchronous jquery-deferred

我有一些ajax调用,每个调用都触发其他ajax调用。然后我想等待后者来处理它们的数据。这是(伪)代码:https://gist.github.com/2795435 问题是第二个$.when-always表达式的回调函数在promises2数组的所有延迟被解析/拒绝之前被触发。怎么会这样?在我看来,第一个$.when-always回调将不会被调用,直到promises1数组的所有延迟都被解析/拒绝,并且到那时所有ajax调用已经被promises2调用,因此应该在$.when-always中的所有延迟已被解决/拒绝之前,不会调用第二个promises2的回调。

1 个答案:

答案 0 :(得分:1)

看来,在await()中,jQuery会在触发与 last promises1相关联的回调之前始终回调getJson来回复。因此,在await()中,promises2数组在内部.when()触发其始终回调时缺少一个承诺。

如果我是对的那么你应该能够运行测试以显示(每个json响应一个.get()),在每种情况下,除了一个内部.get之外的其他所有(从不调用doSomethingToTheDataStoredInSomeGlobalVariableBelow()时将完成更多而且永远不会更少。

无论我是否正确,一个解决方法(不是唯一一个我确定的)将是以下几点:

function A() {
    var promisesA = [];
    for (var i = start; i < end; i++) {
        promisesA.push( B(someUri) );
    }
    $.when.apply($, promisesA).always(function() {
        doSomethingToTheDataStoredInSomeGlobalVariableBelow();
    });
}

function B(uri) {
    var d = new $.Deferred(),
        promisesB = [];
    $.getJSON(uri, function(data) {
        someCollectionFrom_data.each(function () {
            promisesB.push($.get(someUriFrom_this, function(data) {
                extractSomeStuffFrom_data_AndStoreInSomeGlobalVariable();
            }));
        });
        $.when.apply($, promisesB).done(function() {
            d.resolve();
        }).fail(function() {
            d.reject();
        });

    }).error(function(){
        d.reject();
    });
    return d;
}

Here's a demo - 使用经过修改的代码使其成为小提琴。

在这里(除了错误)之外,数组promisesA按照$.Deferreduri填充一次,但这次不允许这些延迟在相应的{{{}时自动解析1}}解决/失败。相反,每个Deferred都会在其所有关联的getJSON解析/失败时通过函数.get()s的数组B()进行“手动”解析(其中每个都会捕获几个实例)在由promisesB)形成的封闭中。

此架构可被视为ajax调用(B().json()s)的“向下”级联,具有.get()s的倒数“向上”级联。 (混合.always()s / .done() / .fail()同样适用。)