简体   繁体   中英

Can't access a global array inside $.getJSON function

I am making a 'viewer' for Twitch TV, which shows if TV channels are online,offline or don't exist. I am using the API for Twitch TV. I have saved the channel names in an array, but when I try to append an array item to an HTML element, it shows 'undefined'. The array is a global variable.

My code is in this fiddle .

HTML:

<div class="container-fluid">

<div class="row row-centered">

<div class="col-md-4"></div>  
<!-- This is a div containing divs for each channel --> 
<div class="col-md-4 col-centered" id="displayHere">


</div>
<!-- The container div end here -->
<div class="col-md-4"></div>  

</div>  

</div>

My Javascript:

$(document).ready(function(){
streamsArr=  ["ESl_SC2","OgamingSC2","cretetion","freecodecamp","storbeck","habathcx","RobotCaleb","noobs2ninjas","brunofin","comster404"];

 for(var count=0;count<streamsArr.length;count++){
 $.getJSON("https://api.twitch.tv/kraken/streams/"+streamsArr[count]+"?callback=?",function(data){

  if(JSON.stringify(data.stream)=="null")
   {
       $("#displayHere").append("<div style=\"padding:1%;\"><span style=\"font-size:1.3em;\"> "+streamsArr[count]+"</span><span style=\"color:red;\">OFFLINE</span></div>");//shows 'undefined'
    }
  else if(data.hasOwnProperty("error"))
    {
      $("#displayHere").append("<div style=\"padding:1%;\"><span style=\"font-size:1.3em;\"> "+streamsArr[count]+"</span><span style=\"color:red;\">UNAVAILABLE</span></div>");//shows 'undefined'
    }
  else{
  $("#displayHere").append("<div style=\"padding:1%;\"><span style=\"font-size:1.3em;\"> "+JSON.stringify(data.stream.channel.display_name)+"</span>"+JSON.stringify(data.stream.game)+"</div>");
  }
}); 
 } 
});

Can someone tell me where the fault lies? Thanks.

由于JavaScript具有函数作用域,因此已为变量count创建了一个闭包,这就是为什么count变量的值始终为10的原因。在ES6中,可以在for循环中使用let而不是var ,因此count可以在块范围内进行。

$.getJSON method is asynchronous so For loop may complete before current request returns a result. So value of the variable count becomes 10.

Here is a fiddle that works https://jsfiddle.net/bkw5dLac/1/

 $(document).ready(function(){ streamsArr= ["ESl_SC2","OgamingSC2","cretetion","freecodecamp","storbeck","habathcx","RobotCaleb","noobs2ninjas","brunofin","comster404"]; for(var count=0;count<streamsArr.length;count++){ getJSON(streamsArr[count]); } }); function getJSON(arr){ $.getJSON("https://api.twitch.tv/kraken/streams/"+arr+"?callback=?",function(data){ if(JSON.stringify(data.stream)=="null") { $("#displayHere").append("<div style=\\"padding:1%;\\"><span style=\\"font-size:1.3em;\\"> "+arr+"</span><span style=\\"color:red;\\">OFFLINE</span></div>");//shows 'undefined' } else if(data.hasOwnProperty("error")) { $("#displayHere").append("<div style=\\"padding:1%;\\"><span style=\\"font-size:1.3em;\\"> "+arr+"</span><span style=\\"color:red;\\">UNAVAILABLE</span></div>");//shows 'undefined' } else{ $("#displayHere").append("<div style=\\"padding:1%;\\"><span style=\\"font-size:1.3em;\\"> "+JSON.stringify(data.stream.channel.display_name)+"</span>"+JSON.stringify(data.stream.game)+"</div>"); } }); } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="container-fluid"> <div class="row row-centered"> <div class="col-md-4"></div> <!-- This is a div containing divs for each channel --> <div class="col-md-4 col-centered" id="displayHere"> </div> <!-- The container div end here --> <div class="col-md-4"></div> </div> </div> 

Why OP's code not working as expected

1) Variable count is a global variable to the anonymous callback function in $.getJSON

2) $.getJSON is asynchronous. So anonymous callback function is triggered only after the success of get request.

3) When the anonymous callback executes, value of count will be modified in for loop. In many cases, it becomes 10. Because for loop completes execution before the callback is triggered

Why my fiddle is working

1) I have passed the value of streamArr at count to a local variable arr .

2) Since, arr is local variable to the function getJSON , its value will not be modified in for loop. So anonymous callback function works as expected.

Let's try cleaning up the $.getJSON function up a bit first:

var twitchAPI = "https://api.twitch.tv/kraken/streams/"+streamsArr[count]+"?callback=?"

and then encapsulate the success callback in a closure that has the index bound to it:

$.getJSON(twitchAPI, function(count) {
    return function(data) {
        if (JSON.stringify(data.stream) == "null") {
            $("#displayHere").append("<div style=\"padding:1%;\"><span style=\"font-size:1.3em;\"> " + streamsArr[count] + "</span><span style=\"color:red;\">OFFLINE</span></div>");
        } else if (data.hasOwnProperty("error")) {
            $("#displayHere").append("<div style=\"padding:1%;\"><span style=\"font-size:1.3em;\"> " + streamsArr[count] + "</span><span style=\"color:red;\">UNAVAILABLE</span></div>");
        } else {
            $("#displayHere").append("<div style=\"padding:1%;\"><span style=\"font-size:1.3em;\"> " + JSON.stringify(data.stream.channel.display_name) + "</span>" + JSON.stringify(data.stream.game) + "</div>");
        }
    }
}(count));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM