如何等待整个AJAX请求循环完成下一个代码块?

时间:2017-06-07 13:15:40

标签: javascript jquery ajax asynchronous

我的目标是使用$.ajax调用从API获取数据,将每个成功的数据推送到数组中,在获取所有数据(所有ajax停止)后,我将它们附加到html页面。
虽然下面的代码通过使用$(document).ajaxStop()满足了我的目标,但我想问一下,是否有任何不同的方式等待,直到所有ajax在一个循环中从i完成到n次?关键在于未来,也许我只需要在循环停止/完成中获取所有ajax来获取一些数据,用它做一些事情,然后在那之后调用一些ajax,但是当我的整个脚本中的所有ajax停止时都不行? (ajaxStop()对我的使用可能在任何时候都没用。)

$(document).ready(function() {
  var streamList = ["HSdogdog", "AdmiralBulldog", "vanNDota", "DreamLeague", "WubWoofWolf", "17uu", "lamperkat", "febbydoto", "Arteezy", "AmazHS", "Moonmeander", "WagamamaTV", "dotademon", "feardota", "esl_dota2", "monkeys_forever", "Dendi", "sheevergaming", "BigDaddy", "Draskyl", "Chessie", "FollowAkke", "bOne7", "attackerdota", "noobfromua", "egm", "qojqva", "alohadancetv", "pajkattdota", "dotastarladder_en", "barnyyy", "zai", "aui_2000", "universedota", "ppd", "fogged", "purgegamers", "meraclechamlotte", "7ckngmad", "miracle_doto", "puppey", "h4nn1", "420jenkins", "illidanstrdoto", "sumaildoto", "jeraxai", "grandgrant", "jeyodude", "bananaslamjamma", "yawar_", "merlinidota", "beyondthesummit", "s4", "stormspirittv", "synderen", "funn1k", "emperorpenguin83", "kano", "miserytheslayer", "reimudesu", "shigetora", "matumbaman", "era17", "sneykingdota", "siractionslacks", "moodota2", "dizzykitten", "sakurafrost225", "Rafis0", "odpixel", "d47biryu", "vampyrette", "w33haa", "blitzdota", "ritsugamer", "limmp", "himegurecia", "dotamajor", "babyknight", "ccncdota2", "lil_hardy", "angelsimosu", "vankhoahoang", "resolut1ontv", "blackdotatv", "sing_sing", "midone", "eternalenvyy", "dotacapitalist", "keemerah", "osu_HDHR", "mssdota", "epicenter_en1", "koushudota", "yapzordota", "moonducktv", "pikachama", "qSnake_", "stan_king", "dota2fata", "madaradota2", "braxton911", "cr1tdota", "mikah138", "evilgeniuses", "dotagasm", "official_niqua", "arise_3012", "nooneboss", "forev", "ramzesdoto", "aliastar", "bububu", "0timado0", "envybaer", "smashdota", "nurbika", "brinkdota", "canceldota", "qodota2", "day9tv", "zingle313", "kvhdota", "abed_dota", "ohaiyodota", "boris_dota", "gorgcc", "ltt98", "pgl_dota", "spare", "hfndota", "happystick", "itshafu", "thijshs", "qsnake", "lizzarddota2", "ek0p", "godot", "chainsito11", "freecodecamp", "aepicenter_en2", "Clarkeezy", "NoctisAK47", "Solitary_Judge"];
  var online = [];
  var offline = [];
  var k = 0;
  var promise = [];
  var promise2 = [];
  for (let i = 0; i < streamList.length; i++) {
    var request = $.ajax({
      url: "https://api.twitch.tv/kraken/streams/" + streamList[i] + "?client_id=rznf9ecq10bbcwe91n6hhnul3dbpg9",
      dataType: 'json'
    });
    promise.push(request);
    request.done(function(data) {
      if (data.stream !== null) {
        online[k++] = {
          channel: data.stream.channel.display_name,
          game: data.stream.game,
          title: data.stream.channel.status,
          viewer: data.stream.viewers,
          icon: data.stream.channel.logo
        };
      } else if (data.stream === null) {
        var request2 = $.ajax({
          url: "https://api.twitch.tv/kraken/channels/" + streamList[i] + "?client_id=rznf9ecq10bbcwe91n6hhnul3dbpg9",
          dataType: 'json'
        });
        promise2.push(request2);
        request2.done(function(data2) {
          offline.push({
            channel: data2.display_name,
            game: data2.game,
            title: data2.status,
            viewer: "Offline",
            icon: data2.logo
          });
        });
      }
    });
  }

  $.when.apply($, promise).then(function() {
    $.when.apply($, promise2).then(function() {
      console.log("this is the final line of console.log");
      $("table").addClass("animated fadeIn");
      $(".loading").detach();
      online.sort(function(a, b) {
        if (a.viewer > b.viewer) {
          return -1;
        } else if (a.viewer < b.viewer) {
          return 1;
        }
        return 0;
      });

      $("thead").append("<tr><th style='width:25%' class = 'channel'>Channel</th><th class = 'game' style = 'width:20%'>Game</th><th>Title</th><th style = 'width: 15%'>Viewers</th></tr>");

      for (var i = 0; i < online.length; i++) {
        if (online[i].icon !== null) {
          $(".table").append("<tr><td class='name'><img class ='icon' src ='" + online[i].icon + "'>" + online[i].channel + "</td><td>" + online[i].game + "</td><td>" + online[i].title + "</td><td><span id='red'></span> " + online[i].viewer + "</td></tr>");
        } else if (online[i].icon === null) {
          $(".table").append("<tr><td class='name'><img class ='icon' src='https://i.imgur.com/0C7WUis.png'>" + online[i].channel + "</td><td>" + online[i].game + "</td><td>" + online[i].title + "</td><td><span id='red'></span> " + online[i].viewer + "</td></tr>");
        }
      }

      for (var j = 0; j < offline.length; j++) {
        if (offline[j].icon !== null) {
          $(".table").append("<tr><td class='name' style='color:#B2ADBF'><img class ='icon-offline' src ='" + offline[j].icon + "'>" + offline[j].channel + "</td><td style='color:#B2ADBF'><em>" + offline[j].game + "</em></td><td style='color:#B2ADBF'>" + offline[j].title + "</td><td style='color:#B2ADBF'>" + offline[j].viewer + "</td></tr>");
        } else if (offline[j].icon === null) {
          $(".table").append("<tr><td class='name' style='color:#B2ADBF'><img class ='icon-offline' src='https://i.imgur.com/0C7WUis.png'>" + offline[j].channel + "</td><td style='color:#B2ADBF'><em>" + offline[j].game + "</em></td><td style='color:#B2ADBF'>" + offline[j].title + "</td><td style='color:#B2ADBF'>" + offline[j].viewer + "</td></tr>");
        }
      }

      $("tbody tr").click(function() {
        window.open("https://www.twitch.tv/" + $(this).find('td.name').text());
      });
    });
  });


});

编辑1:在浏览了与$ .when(passing array of deferreds)相关的许多主题以及如何处理nested AJAX calls之后,我终于实现了我想要的目标(我编辑了我的代码片段,基本上使用嵌套的$ .when并且你传递了promises数组)。然而,出现了一个新问题,只有当所有promises都解决了(所有AJAX调用成功返回数据)时,我的代码才能很好地工作。在AJAX调用失败的情况下,即AJAX调用返回后未找到的数据,内部promises数组将无法解析,因此永远不会将数据附加到HTML页面中。所以我尝试将$.when.apply($, promise2).then(function())更改为$.when.apply($, promise2).always(function(),但always似乎无法正常工作,因为只要AJAX调用返回错误,它就会将数据追加到我的HTML页面,因此在追加完成后将会请求缺少数据,因此我作为指标尝试的console.log("This is the final line ...")不再出现在最后一行。我错过了.always().的内容,因为它不会等待$.when()确保所有承诺都被拒绝或解决,而是在任何承诺被拒绝时运行。

编辑2 :如果有人仍感兴趣,我终于解决了我的问题。上面我误解的$.always()实际上是按预期工作的,如果任何承诺被拒绝,它将在$.always()之后执行该函数,即使数组中还有更多未决的承诺。所以感谢这个comment,我所做的基本上是映射promise2数组的所有promise(将失败的数组的数组),以便在调用时解析状态。这是片段:

promise2 = $.map(promise2, function (p) {          
       var dfd = $.Deferred();
       p.always(function () {
          dfd.resolve();
       });
       return dfd.promise();
}

0 个答案:

没有答案