对可变数量的ajax请求使用jquery deferreds

时间:2013-02-20 20:48:34

标签: javascript jquery jquery-deferred

当我有一个可变数量的ajax请求时,如何使用延迟调用它们?

我的猜测:

//qty_of_gets = 3;

function getHTML(productID, qty_of_gets){

    var dfd = $.Deferred(),
            i = 0,
            c = 0;

    //this is where there could be some magic to 
    //do multiple ajax posts
    //obviously I'm out of my depth here...
    while (i <= qty_of_gets){

        dfd.pipe(function(){
            $.get("queries/html/" + product_id + i + ".php");
        });                       
    i++
    }
    dfd.done(function(){

        while (c <= qty_of_gets){
           $('myDiv').append(c);
           c++;
        }

    });
}

2 个答案:

答案 0 :(得分:6)

如果要按顺序执行Ajax调用,则必须从回调中返回promise,并将新回调附加到最后一个promise对象:

var dfd = $.Deferred(),
   promise = dfd.promise(),
   i = 0,
   c = 0;

while (i <= qty_of_gets) {
    // needs an IIFE
    (function(i)
        promise = promise.then(function(){
            return $.get("queries/html/" + product_id + i + ".php");
        });
    }(i++));                       

}

promise.done(function(){

    while (c <= qty_of_gets){
       $('myDiv').append(c);
       c++;
    }

});

// resolve deferred
dfd.resolve();

从jQuery 1.8开始,您应该使用.then而不是.pipe

另一个问题是(至少在你的例子中),在执行回调时,i将没有你期望的值。您可以使用立即调用的函数表达式来捕获i的当前值。有关详细信息,请参阅JavaScript closure inside loops – simple practical example


获得结果没有干净的解决方案。我认为您可以做的最好的事情是将结果添加到数组并在.done回调中访问该数组。即:

var results = [];

while (i <= qty_of_gets) {
    // needs an IIFE
    (function(i)
        promise = promise.then(function(){
            return $.get("queries/html/" + product_id + i + ".php")
                     .then(function(result) {
                       results[i] = result;
                     });
        });
    }(i++));                       

}

promise.done(function(){
    // do something with `results`
});

答案 1 :(得分:3)

关闭,您需要从.pipe回调中返回一个promise对象。
请参阅felix的回答,下一个示例还有其他问题,而不仅仅是返回丢失。

dfd.pipe(function(){
    return $.get("queries/html/" + product_id + i + ".php");
});  

另外,我认为它实际上并没有写在任何地方,但 .pipe在最新版本的核心中实现如下:

promise.pipe = promise.then

因此, 可以用dfd.pipe替换dfd.then 参考:http://api.jquery.com/deferred.pipe/

提到的另一个替代方法是使用$.when

function getHTML(productID, qty_of_gets) {

    var dfdArr = [];

    while (i <= qty_of_gets) {
        dfdArr.push($.get("queries/html/" + product_id + i + ".php"));
        i++
    }
    $.when.apply(null, dfdArr).done(function () {

        for (response in arguments) {
            $('#myDiv').append(response[0]);
        }

    });
}