有人能告诉我为什么我的console.log为每个循环返回相同的输出以及如何修复它? console.log应该返回'频道的每个元素。数组,但它不断输出最后一个元素' noobs2ninjas'。
它与FCC Twitch应用here的功能类似。不同之处在于我交换了。$ getJSON命令。他们的应用程序正在获得“流”。首先,当我获得“通道”#39;第一。我一直在比较我的代码和他们的代码,并且无法理解为什么内部。$ getJSON将一遍又一遍地重复相同的数组元素但是outter。$ getJSON正在循环遍历每个元素。
function loadChannel() {
var channels = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
var display_name = null;
var logo = null;
var url = null;
var game = null;
var status = null;
var online = false;
function api(type, channel) {
return `https://api.twitch.tv/kraken/${type}/${channel}?callback=?`;
}
for (var index in channels) {
$.getJSON(api('channels', channels[index]), function(data) {
display_name = data.display_name;
logo = data.logo;
url = data.url;
game = data.game;
status = data.status;
$.getJSON(api('streams', channels[index]), function(data) {
// get online status
console.log(channels[index]); // <-- outputs same channel 'noobs2ninjas' each loop
console.log(data); // <-- outputs same object each loop
});
});
}
}
答案 0 :(得分:1)
因为$.getJSON
是异步的,并且在调用其回调时,循环已经结束,index
将保持循环的最新值。
您应该bind
将您的函数index
作为第一个参数,如:
for (var index in channels) {
(function(i){
$.getJSON(api('channels', channels[i]), function(data){
...
// channels[i] is what you want here
$.getJSON(api('streams', channels[i]), function(data) {
...
});
});
}.bind(null, index))()
}
但在这种特定情况下,为什么不channels.forEach(function(channel){ ... }
?
答案 1 :(得分:1)
这是因为Javascript中的var
是函数作用域,而不是块作用域;您的var index
声明被提升到loadChannels的顶部,并被覆盖每个循环。这意味着您的异步函数只访问最后一个索引,因为循环在ajax调用之前完成。 是一个很好的解决方案,你已经非常接近了。
使用现有代码,您可以只切换for循环,而是使用Array.forEach
。您将向它传递一个函数,该函数将创建一个新的作用域,其中 channel 在本地作用于循环(因此在每次迭代时都不会被覆盖)。
function loadChannel() {
var channels = ["ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas"];
var display_name = null;
var logo = null;
var url = null;
var game = null;
var status = null;
var online = false;
function api(type, channel) {
return `https://api.twitch.tv/kraken/${type}/${channel}?callback=?`;
}
channels.forEach(function (channel) {
$.getJSON(api('channels', channel), function(data) {
display_name = data.display_name;
logo = data.logo;
url = data.url;
game = data.game;
status = data.status;
$.getJSON(api('streams', channel), function(data) {
// get online status
console.log(channel); // <-- should be fixed
console.log(data); // <-- outputs same object each loop
});
});
});
}
将您计划在循环中使用的任何其他变量的声明(display_name,logo等)移动到我们刚刚制作的forEach中也可能是明智之举。
参考文献: