我的目标是使用$.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();
}