收到AJAX内容时,$ .each的下一次迭代

时间:2016-04-13 12:46:50

标签: javascript jquery ajax asynchronous jquery-deferred

问题是asked before,但差不多四年前,也许有更好的解决方案。

我有一个$ .each循环,其中有时通过ajax获取其他数据。

我使用获取的数据构建对象,在循环之后有一个从对象生成HTML的函数。 问题是循环在ajax数据到达之前完成。如果我在HTML生成函数中发出警报,则内容正在正确加载。

我正在寻找一种只在循环和所有ajax调用完成时调用HTML-generator-function的解决方案。也许这是一个计算已启动的Ajax请求的解决方案,并等待所有这些请求都完成了?

我相信jQuery deferred对我来说是正确的解决方案,但我确实只找到了所有内容都在循环中的示例。有人可以帮忙吗?

我已将我的代码删除到最重要的事情:

//goes through each testplace -->main loop
$.each(jsobject, function(key, value)
{
 //build object together...
  for (var i = 0, numComputer = jenkinsComputer.contents.computer.length; i < numComputer; i++)
  {
    //If the testplace is in both objects then fire AJAX request
    if (jenkinsComputer.contents.computer[i].displayName == key) //<<<This can happen only once per $.each loop, but it does not happen every time
    {
      //next $.each-iteration should only happen when received the JSON
      var testplaceurl = jenkinsComputer.contents.computer[i].executors[0].currentExecutable.url;
      $.when($.getJSON("php/ba-simple-proxy.php?url=" + encodeURI(testplaceurl) + "api/json?depth=1&pretty=1")).done(function(jenkinsUser) 
      {
        //build object together...
      });
    }
  }

}); //End of main Loop ($.each)
generateHTML(builtObject);

如果有人可以给我一个如何做的建议,那就太好了。

2 个答案:

答案 0 :(得分:0)

这是关于解决方案的一个未经测试的简短示例。我希望这能给你一个想法。

// I guess that jsobject is array ..
// if it is not object you can use something like:
// var keys = Object.getOwnPropertyNames(jsobject)
(function () {
    var dfd = $.Deferred();

    function is_not_finished() {
        return jsobject.length > 0 && jenkinsComputer.contents.computer.length > 0;
    }

    (function _handleObject() {
        var key = jsobject.shift();
        var displayName = jenkinsComputer.contents.computer.shift().displayName;

        if (displayName == key) //<<<This can happen only once per $.each loop, but it does not happen every time
        {
            //next $.each-iteration should only happen when received the JSON
            var testplaceurl = jenkinsComputer.contents.computer[i].executors[0].currentExecutable.url;
            $.getJSON("php/ba-simple-proxy.php?url=" + encodeURI(testplaceurl) + "api/json?depth=1&pretty=1").done(function(jenkinsUser)
            {
                //build object together...
                if(is_not_finished()) {
                    setTimeout(_handleObject,0);
                } else {
                    dfd.resolve();
                }
            });
        } else if (is_not_finished()) {
            setTimeout(_handleObject,0);
        } else {
            dfd.resolve();
        }
    }());

    return dfd.promise();
}()).done(function () {
    generateHTML(builtObject);
});

答案 1 :(得分:0)

我会做这样的事情:

var thingstodo = $(jsobject).length;
var notfired = true;
$.each(jsobject, function(key, value)
{
 //build object together...
  for (var i = 0, numComputer = jenkinsComputer.contents.computer.length; i < numComputer; i++)
  {
    //If the testplace is in both objects then fire AJAX request
    if (jenkinsComputer.contents.computer[i].displayName == key) //<<<This can happen only once per $.each loop, but it does not happen every time
    {
      //next $.each-iteration should only happen when received the JSON
      var testplaceurl = jenkinsComputer.contents.computer[i].executors[0].currentExecutable.url;
      $.when($.getJSON("php/ba-simple-proxy.php?url=" + encodeURI(testplaceurl) + "api/json?depth=1&pretty=1")).done(function(jenkinsUser) 
      {
        //build object together...
        thingstodo--;
        if(thingstodo === 0 && notfired){
            notfired = false;
            generateHTML(buildObject);
        }
      });
    }else{
        thingstodo--;
    }
  }

}); //End of main Loop ($.each)
if(thingstodo === 0 && notfired){
    generateHTML(buildObject);
}