Search code examples
javascriptjsonpromisefetch-api

Using variables from multiple Fetch API requests


I am new to using Fetch API and just started to understand Promises. So what I am asking might be too naive.

I am fetching an event endpoint with a token, getting event details including team ids and then using these team ids to fetch another endpoint. In the end, I am looping through each event and printing event details and team names. This works fine but in the last step, my last variables are undefined.

In the following code, I get:

"Reference Error: homeTeam is not defined"

and "varStart" and "varEnd" also don't work. From all the searching, I believe it has something to do with hierarchy of the promises but I can figure it out. I really appreciate any pointers. My code is:

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>


<script>  
var html = '<tr><td colspan=3 class=superBold> </td></tr>';
var params = {
    grant_type: 'client_credentials',
    client_id: 'xxxx',
    client_secret: 'xxxx'
}

fetch('token_url', {
    method: 'POST',
        body: JSON.stringify(params),
        headers: {
            'Content-Type': 'application/json'
        }

}).then(function(response){
    return response.json()

}).then(function(token_data){
    return fetch('event_url', {
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Bearer' + ' ' + token_data.access_token,
        }

    }).then(function(event_response){
        return event_response.json()

    }).then(function(event_data){
        var len = event_data.data.length
        console.log(event_data)

        for (var i = 0; i < len; i++){
            var varStart = event_data.data[i].attributes.start.substr(11, 5);
            var varEnd = event_data.data[i].attributes.end.substr(11, 5);
            
            var hteam_id = event_data.data[i].attributes.hteam_id;
            var vteam_id = event_data.data[i].attributes.vteam_id;


            let a = fetch('team_url' + hteam_id, {
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': 'Bearer' + ' ' + token_data.access_token,
                }    
            })
            let b = fetch('team_url' + vteam_id, {
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': 'Bearer' + ' ' + token_data.access_token,
                }
            })

            Promise.all([a,b])
            .then(values => Promise.all(values.map(value => value.json())))

            .then(function(team_data){
                let homeTeamResp = team_data[0];
                let awayTeamResp = team_data[1];

                var homeTeam = homeTeamResp.data[0].attributes.name
                let awayTeam = awayTeamResp.data[0].attributes.name

            })
            html += '<tr><td>' + i + '</td><td>' + 'HomeTeam: ' + homeTeam + ' AwayTeam: ' + awayTeam, + '</td><td>'  + 'Start: ' + varStart + ' End: ' + varEnd + '</td></tr>';
        }
        $("#content").append(html);

    })

})

</script> 
</head>
<body>
<div id='content'> </div>
</body>
</html>

Solution

  • You need to move html +=..... line to the final .then as @Travnikov said, One more point is instead of using var i in for loop you need to use let i as suggested by @Piyush you should learn the scopes and it's behaviors in javascript.

    So your final code would be the following,

    <html>
    <head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    
    
    <script>  
    var html = '<tr><td colspan=3 class=superBold> </td></tr>';
    var params = {
        grant_type: 'client_credentials',
        client_id: 'xxxx',
        client_secret: 'xxxx'
    }
    
    fetch('token_url', {
        method: 'POST',
            body: JSON.stringify(params),
            headers: {
                'Content-Type': 'application/json'
            }
    
    }).then(function(response){
        return response.json()
    
    }).then(function(token_data){
        return fetch('event_url', {
            headers: {
                'Content-Type': 'application/json',
                'Authorization': 'Bearer' + ' ' + token_data.access_token,
            }
    
        }).then(function(event_response){
            return event_response.json()
    
        }).then(function(event_data){
            var len = event_data.data.length
            console.log(event_data)
    
            //using 'let i' instead of 'var i'
            for (let i = 0; i < len; i++){
                var varStart = event_data.data[i].attributes.start.substr(11, 5);
                var varEnd = event_data.data[i].attributes.end.substr(11, 5);
    
                var hteam_id = event_data.data[i].attributes.hteam_id;
                var vteam_id = event_data.data[i].attributes.vteam_id;
    
    
                let a = fetch('team_url' + hteam_id, {
                    headers: {
                        'Content-Type': 'application/json',
                        'Authorization': 'Bearer' + ' ' + token_data.access_token,
                    }    
                })
                let b = fetch('team_url' + vteam_id, {
                    headers: {
                        'Content-Type': 'application/json',
                        'Authorization': 'Bearer' + ' ' + token_data.access_token,
                    }
                })
    
                Promise.all([a,b])
                .then(values => Promise.all(values.map(value => value.json())))
    
                .then(function(team_data){
                    let homeTeamResp = team_data[0];
                    let awayTeamResp = team_data[1];
    
                    var homeTeam = homeTeamResp.data[0].attributes.name
                    let awayTeam = awayTeamResp.data[0].attributes.name
    
                    //Here html concatination is happenning
                    html += '<tr><td>' + i + '</td><td>' + 'HomeTeam: ' + homeTeam + ' AwayTeam: ' + awayTeam, + '</td><td>'  + 'Start: ' + varStart + ' End: ' + varEnd + '</td></tr>';
                    $("#content").append(html);
    
                })
                // no need this line
                //html += '<tr><td>' + i + '</td><td>' + 'HomeTeam: ' + homeTeam + ' AwayTeam: ' + awayTeam, + '</td><td>'  + 'Start: ' + varStart + ' End: ' + varEnd + '</td></tr>';
            }
    
        })
    })
    
    </script> 
    </head>
    <body>
    <div id='content'> </div>
    </body>
    </html>