多个each和ajax请求

时间:2013-06-27 07:52:31

标签: javascript jquery ajax callback

所以这是我的设置:我在一些元素上调用.each,经过几次检查后,我发送了一个带有一些JSON数据的ajax请求,并且在成功时我将服务器响应作为属性应用于每个元素(它通常是一个id)。之后我将id推送到数组。

问题是,显然ajax请求是异步的,并且在所有ajax有时间完成之前,使用元素id数组的函数会触发。

我已经尝试过.when和.then,但回调函数一直在ajax之前被激活。

以下是我的代码的外观(我删除了一些不必要的部分):

var order = [];

function sub(selector){

selector.each(function(){
    var out = {
        "some":"random",
        "stuff":"here"
    };
        $.ajax({
            type: "POST" 
            url: "/test/url",
            dataType: 'json',
            contentType: "application/json; charset=utf-8",
            data:JSON.stringify(out),
            success:function(response){
                $(this).attr("data-response",response);
                order.push(response);
            }
        })
    })
}

$("#button").click(function(){
    $.when(sub($(".test"))).then(function() {
        console.log(order);
        //i have to run the sub function twice so the order doesn't return undefined
    });     
});

5 个答案:

答案 0 :(得分:1)

问题是when会对延迟对象起作用,但是子不会返回任何内容,因此when会立即触发。所以你需要做的是收集ajax调用返回的所有延迟对象并返回它们:

var order = [];

function sub(selector){
    var deferredList = []
    selector.each(function(){
        var out = {
            "some":"random",
            "stuff":"here"
        };
        var deferred = $.ajax({
                type: "POST", 
                url: "/test/url",
                dataType: 'json',
                contentType: "application/json; charset=utf-8",
                data:JSON.stringify(out),
                success:function(response){
                    $(this).attr("data-response",response);
                    order.push(response);
                }
            })
        deferredList.push(deferred)
    })
    return deferredList;
}

$("#button").click(function(){
    $.when.apply($,sub($(".test"))).then(function() {
        console.log(order);
        //i have to run the sub function twice so the order doesn't return undefined
    });     
});

直接使用apply而非when的原因是when不接受对象数组作为参数,apply为我们提供了工作 - 为了这个。

答案 1 :(得分:0)

$.when()的参数应为Deferred,但sub()不返回任何内容。此版本返回Deferred返回的所有$.ajax的数组,并将$.when作为参数调用;然后它将等待所有这些。

var order = [];

function sub(selector){
    return selector.map(function(){
        var out = {
            "some":"random",
            "stuff":"here"
        };
        return $.ajax({
            type: "POST" 
            url: "/test/url",
            dataType: 'json',
            contentType: "application/json; charset=utf-8",
            data:JSON.stringify(out),
            success:function(response){
                $(this).attr("data-response",response);
                order.push(response);
            }
        })
    })
}

$("#button").click(function(){
    $.when.apply(this, sub($(".test"))).then(function() {
        console.log(order);
        //i have to run the sub function twice so the order doesn't return undefined
    });     
});

答案 2 :(得分:0)

您的方法会产生更多的服务器请求,并且会非常严重。既然你想要等待所有结果,一个更好的解决方案是收集所有数据并只发送一个ajax请求,它返回每个数据对象的结果数组。

使用延迟对象(如其他答案中所示),然后您可以在when语句中使用该结果。

答案 3 :(得分:0)

尝试成功使用回调函数:

var order = [];

function sub(selector, callback){

selector.each(function(){
    var out = {
        "some":"random",
        "stuff":"here"
    };
        $.ajax({
            type: "POST" 
            url: "/test/url",
            dataType: 'json',
            contentType: "application/json; charset=utf-8",
            data:JSON.stringify(out),
            success:function(response){
                $(this).attr("data-response",response);
                order.push(response);
                callback();
            }
        })
    })
}

$("#button").click(function(){
    sub($(".test"), function() { console.log(order) });
});

答案 4 :(得分:-2)

将属性async:false添加到$ .ajax - call。然后在彼此之后按顺序进行调用。