1

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

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

我已经尝试过 .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
    });     
});
4

5 回答 5

1

问题是when作用于延迟对象,但是 sub 不会返回任何东西,所以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为我们提供了解决方法。

于 2013-06-27T08:06:57.993 回答
0

您的方法会产生更多的服务器请求,并且会扩展得非常厉害。由于您无论如何都想等待所有结果,因此更好的解决方案是收集所有数据并仅发送一个 ajax 请求,该请求为每个数据对象返回一组结果。

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

于 2013-06-27T08:15:54.567 回答
0

to 的参数$.when()应该是 a Deferred,但sub()不返回任何内容。Deferred此版本返回由 s 返回的所有 s的数组$.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
    });     
});
于 2013-06-27T08:10:42.127 回答
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) });
});
于 2013-06-27T08:24:53.447 回答
-2

将属性 async : false 添加到您的 $.ajax - 调用中。然后依次进行呼叫。

于 2013-06-27T08:13:58.490 回答