【问题标题】:Multiple each and ajax requests多个each和ajax请求
【发布时间】:2013-06-27 07:52:31
【问题描述】:

所以这是我的设置:我在多个元素上调用 .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
    });     
});

【问题讨论】:

  • 您可以继续检查 order 数组中的 itmes 数量,直到它与 selector.each 的大小相同。使用 setInterval

标签: javascript jquery ajax callback


【解决方案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 为我们提供了解决此问题的方法。

【讨论】:

  • 这也会在所有 ajax 之前触发(订单数组中的所有值都是未定义的)
  • 对我有用,您的代码中的问题可能在其他地方
【解决方案2】:

$.when() 的参数应该是Deferred,但sub() 不返回任何内容。此版本返回由$.ajax 返回的所有Deferreds 的数组,并以它们作为参数调用$.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
    });     
});

【讨论】:

  • 不应该是success$.ajax给出的返回对象的方法吗?
  • $.ajax() 返回一个jqXHR 对象,它实现了Promise 接口以及.done() 等特定于AJAX 的方法。
  • 我试过了,但在所有 ajax 完成之前它仍然会触发
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    尝试使用回调函数成功:

    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) });
    });
    

    【讨论】:

      【解决方案5】:

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

      【讨论】:

      • 这是一个糟糕的解决方案 - 使用异步调用是有充分理由的。
      • 这会让事情变得更慢
      • 是的,它会让它变慢。我刚刚回答了这个问题,它会起作用。如果性能是一个问题,OP 应该重写代码,以便每个函数调用只完成一个服务器请求(如果可能)
      猜你喜欢
      • 1970-01-01
      • 2011-11-28
      • 1970-01-01
      • 2013-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-05
      相关资源
      最近更新 更多