Search code examples
arraysvariablestwitch

javascript accessing array outside of function


So I am making this twitch.tv api page for free code camp. I am trying to iterate through the streamers array and push the data to the results array, sort by # of viewers and display the data from the results array on the page.

The problem is while the the .append stuff is in the for loop in writes the infor multiple times. If I move it out of the for loop, the variables are undefined.

Any ideas out there from the smart people?

    $(document).ready(function(){
    getInfo();  
    var results = [];
    function getInfo(){
        var streamers = ["FreeCodeCamp","PlayHearthstone","summit1G","BradfordLee","Savjz","Z28RyanK"];
    streamers.forEach(function(streamers){
            $.getJSON('https://wind-bow.gomix.me/twitch-api/channels' + '/' + streamers + '?callback=?', function(data){

                var name = data.display_name;
                var game = data.game;
                var logo = data.logo;

                $.getJSON('https://wind-bow.gomix.me/twitch-api/streams' + '/' + streamers + '?callback=?', function(data){
                    var status = data.stream;
                    if(data.stream == undefined){
                        status = "Offline";
                    }else{
                        status = "Online";
                    }
                    var views = data.stream;
                    if(data.stream == undefined){
                        views = 0;
                    }else{
                        views = data.stream.viewers;
                    }
                    results.push({"name": name, "logo": logo, "status": status, "game": game, "views": views});
                    results.sort(function(b, a) {return parseFloat(a.views) -parseFloat(b.views);});
                    console.log(results);
                    results.forEach(function(results){
                        $('.main').append('<div><img src="' + logo + '"><p>' + name + '</p><p>' + status + '</p><p>' + game + '</p><p>' + views + '</p></div>');
                    })                      
    }   )               
})          
            })      
        }
    });

Solution

  • You can move out the append line. You say you don't have access to the variables, but you just stored them in the results array, so you can access them from there. So simply move out the line and change is as such:

    results.forEach(function(result){
        $('.main').append('<div><img src="' + result.logo + '"><p>' + result.name + '</p><p>' + result.status + '</p><p>' + result.game + '</p><p>' + result.views + '</p></div>');
    }) 
    

    (Do note that you shouldn't do results.forEach(function(results){ using the name results twice, similar with streamers. You're running a forEach over results, so it's for each result (not plural))

    Below I have rewritten your piece of code, fixing some errors. See it in action in this fiddle.

    var streamers;
    var streamCallsCompleted;
    var results;
    
    $(document).ready(function() {
        streamers = ["FreeCodeCamp", "PlayHearthstone", "summit1G", "BradfordLee", "Savjz", "Z28RyanK"];
        results = [];
        streamCallsCompleted = 0;
    
        getAndAppendInfo(streamers);
    
        // parseFloat shouldn't be necessary as views should be a whole number
        results.sort(function(b, a) {
            return parseInt(a.views) - parseInt(b.views);
        });
    
    
    });
    
    function getAndAppendInfo(streamers) {
        streamers.forEach(
            function(streamer) {
                $.getJSON('https://wind-bow.gomix.me/twitch-api/channels' + '/' + streamer + '?callback=?', function(data) {
                channelCallSuccess(data, streamer)
                })
                    .fail(channelCallError);
            });
    }
    
    function channelCallError() {
        streamCallsCompleted++;
    
        checkAndAppendResults();
    }
    
    function streamCallError() {
        streamCallsCompleted++;
    
        checkAndAppendResults();
    }
    
    function channelCallSuccess(data, streamer) {
    
    
        var name = data.display_name;
        var game = data.game;
        var logo = data.logo;
    
        $.getJSON('https://wind-bow.gomix.me/twitch-api/streams' + '/' + streamer + '?callback=?', function(data) {
            streamCallsCompleted++;
    
            var status = data.stream ? "Online" : "Offline";
            var views = data.stream ? data.stream.viewers : 0;
    
            results.push({
                "name": name,
                "logo": logo,
                "status": status,
                "game": game,
                "views": views
            });
    
            checkAndAppendResults();
        });
    }
    
    function checkAndAppendResults() {
        if (streamCallsCompleted < streamers.length) {
            return;
        }
    
        console.log(results);
        results.forEach(function(result) {
            $('.main').append('<div><img src="' + result.logo + '"><p>' + result.name + '</p><p>' + result.status + '</p><p>' + result.game + '</p><p>' + result.views + '</p></div>');
        });
    }
    

    Basically, the gist here is that the getJSON call is asynchronous. This means that this piece of code is not executed in order. As such we have to keep track of how many calls we make. Only when all calls have either succeeded or erred, we will process the results.