getJSON里面的Jquery getJSON是同步的

时间:2016-05-16 14:57:33

标签: javascript jquery json loops getjson

我有以下代码通过$.getJSON连接到API,接受JSON然后通过for循环循环3次(因为它有3个对象data.length)。在这3次迭代中的每次迭代中,它创建另一个$.getJSON以从第一次连接的迭代中获取具有所需参数的特定新数据。

    var baseAPI = "https://api.guildwars2.com/";
    var versionAPI = ["v1", "v2"];
    var endpointAPI = ["account", "guild_details.json", "guild", "stash", "items"];
    var bearerAPI = ["access_token", "guild_id"];

    $('#keyInput_user_FORM').on('submit', function(e) {
        e.preventDefault();
        var mordant = "https://api.guildwars2.com/v2/guild/927CDDD7-4E8D-E411-A8E7-AC162DAE5A05/stash?access_token=EDCD27E4-3A1B-3C44-9C5B-99F062596A9BB1C9C824-AE01-4F6F-9EA9-CBAD2D721C9D";
        $(".JuilsContainer").append('<div class="bankResult"></div>');

        $.getJSON( encodeURI(mordant), {
            tagmode: "any",
            format: "json"
        }).done(function( data ) {
            for(var bankCount = 0; bankCount < data.length; bankCount++){
                $(".bankResult").append('<div class="inventory" id="upgradeID_'+data[bankCount].upgrade_id+'"><header>'+data[bankCount].note+'</header><ul class="inventory_UL"></ul></div>');
                $.each( data[bankCount].inventory, function( i, inventory ){ /*can also run on property .size but running inventory guarantees not running more or less than there are items instead of slots.*/
                    if(data[bankCount].inventory[i] != null){
                        var accountAPI = baseAPI + versionAPI[1] + "/" + endpointAPI[4] + "/" + data[bankCount].inventory[i].id;
                        $.getJSON( encodeURI(accountAPI), {
                            tagmode: "any",
                            //async: false,
                            format: "json"
                        }).done(function( item_data ) {
                            $('#upgradeID_'+ data[bankCount].upgrade_id + ' .inventory_UL').append('<li class="bankInventory_item" id="item_'+item_data.id+'"><img src="'+encodeURI(item_data.icon)+'"><span class="itemCount">'+ data[0].inventory[i].count + '</span></li>');
                        });
                    }else{
                        $('#upgradeID_'+ data[bankCount].upgrade_id + ' .inventory_UL').append('<li class="bankInventory_item" class="item_null"></li>');   
                    }
                });
            }
        });

    });

遗憾的是,第一次循环中的所有$.getJSON次调用都是在完成3次迭代后完成的,循环结束。我希望第二个连接在循环内部生效,而不是在完成循环3次之后生效。

此外,由于某种原因,当它到达所有第二个$.getJSON调用时,它不使用正确的迭代var。变量bankCount似乎是3,而它只能达到2,因为它有3个对象可以计数和循环。

这就发生在这条线上。

$('#upgradeID_'+ data[bankCount].upgrade_id + ' .inventory_UL').append('<li class="bankInventory_item" id="item_'+item_data.id+'"><img src="'+encodeURI(item_data.icon)+'"><span class="itemCount">'+ data[0].inventory[i].count + '</span></li>');

当它尝试使用data[bankCount].upgrade_id时,bankCount似乎是3,而只有3个对象(因此它最多应为2,因为不再有。)

所有$.getJSON次来电都不会马上执行。它们以某种方式排队,直到完成所有循环。只有当它完成从第一个$.getJSON循环完成3次后才执行,并从循环内排队的那些返回全部。 ^编辑问题,希望更清晰

当只有3个对象时,变量bankCount如何变为3(因此应该是最大值2)。

1 个答案:

答案 0 :(得分:0)

侧点:当你将async设置为false时,我不确定为什么代码没有做你想要的。但是,我说,这并不是一个有趣的案例,因为你真的不想进行同步的ajax调用 - 它只是导致无响应的网页和一般糟糕的用户体验。

所以,我要把你的问题翻译成: “我想循环遍历一组对象;在每个对象上异步调用$ .getJSON;并且只在前一个调用完成后才启动每个调用。”

您可以通过在前一次调用的.done处理程序中每次调用$ .getJSON来执行此操作。

如果您的数据中只有三个元素,那么您可以通过将三个调用嵌套到$ .getJSON以简单(但难看)的方式执行此操作。

但是,我认为你的数据可以是任意长度的。这迫使你使用更清洁的解决方案......

您需要使用递归调用替换for循环迭代。

如下所示:

...
submitHelper(data, 0);
...

function submitHelper(data, pos) {
  if (pos >= data.length) {
    return;
  }
  $.getJSON(..., done: function(itemData) {
    ...
    submitHelper(data, pos++);
    }
...