当接收到AJAX内容时,每次$.的下一次迭代

Next iteration of $.each when received AJAX-content

本文关键字:迭代 一次 每次 AJAX      更新时间:2024-06-12

这个问题以前也有人问过,但现在已经差不多四年了,也许有更好的解决方案。

我有一个$.each循环,有时会通过ajax获取额外的数据。

我正在用提取的数据构建一个对象,在循环之后,有一个函数可以从该对象生成HTML问题是循环在ajax数据到达之前就完成了如果我在HTML生成函数中放置警报,则内容加载正常。

我正在寻找一种解决方案,它只在循环和所有ajax调用完成时调用HTML生成器函数。也许计算已启动的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);

如果有人能给我一个如何做的建议就太好了。

我会这样做:

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

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

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