Leveraging data from various Fetch API calls to access a range of

As a beginner with Fetch API and Promises, I have encountered an issue that I hope someone can help me with.

My code involves fetching event data with a token, extracting team ids, and using these ids to fetch more information from another endpoint. Everything seems to be working fine until the last step where my variables are showing up as undefined.

Specifically, when running the code, I receive the error message:

"Reference Error: homeTeam is not defined"

I am also facing problems with "varStart" and "varEnd". Despite researching extensively, I'm unable to pinpoint the exact cause of the issue but I suspect it has something to do with promises hierarchy.

Below is a snippet of my code:

<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>

Answer №1

To optimize your code, make sure to shift the html +=..... line to the final .then block as suggested by @Travnikov. Another important detail is switching from using var i in the for loop to let i as recommended by @Piyush to grasp the concept of scopes and behaviors in javascript.

Your modified code should look like this:

<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 concatenation is taking place
                html += '<tr><td>' + i + '</td><td>' + 'HomeTeam: ' + homeTeam + ' AwayTeam: ' + awayTeam, + '</td><td>'  + 'Start: ' + varStart + ' End: ' + varEnd + '</td></tr>';
                $("#content").append(html);

            })
            // omitting this line as it's unnecessary
            //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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Limit the rotation of jQuery and CSS3 elements to always turn in a clockwise direction

Utilizing the jQuery transit plugin, I am rotating a block element with 4 navigation controls. Each time a nav item is clicked, the block rotates to the specified custom data attribute of that nav item - either 0, 90, 180, or 270 degrees. While I have suc ...

Parent's hover element

I am currently working with the following loop: <?php if( have_rows('modules') ): $counter = 0; while ( have_rows('modules') ) : the_row(); ?> <div class="col span_4_of_12 <?php if($counter == 0) { ?>firs ...

Unable to access a frame inside an iframe and frameset using JavaScript when both domains are identical

I am attempting to use JavaScript to access an HTML element within a nested frame in an iframe and frameset. The structure of the HTML is as follows: <iframe id="central_iframe" name="central_iframe" (...)> <frameset cols="185, *" border="0" ...

What could be causing the error when trying to submit to OData Edm.Decimal type?

Having an issue submitting JSON to an OData service. The $metadata indicates it expects this format: <Property Name="curClaimValue" Type="Edm.Decimal" Nullable="true" Precision="19" Scale="4"/> This snippet is from my JSON data: ..."curClaimValue" ...

Perform a series of clicks

I'm attempting to click a button multiple times. After each click, the button takes 1 second to load, then reappears and can be clicked again. My goal is to click this button a total of 5 times. for(i=0;i<5;i++) $('.class').click(); ...

Angular JS does not acknowledge null values

Within my controller, the variable $scope.test is assigned a value from the server. When this value is null, line 1 of the code below prints 'null', however it still enters the else condition. I have attempted to use $scope.test != null and $scop ...

Function for testing global variable stub in JavaScript

Currently, I am in the process of writing Unit tests for a React application. Within the page header, the tracking library 'mixpanel' is inserted between <script> tags as outlined in their documentation: . The documentation states that "Th ...

Using JavaScript (AJAX), learn the process of incorporating XML data within HTML files

I'm relatively new to HTML and I'm attempting to create a self-contained HTML page that includes all necessary CSS, data, and JavaScript within the file itself. While I understand that this will result in a rather messy HTML document, it is essen ...

React hooks causing dynamic object to be erroneously converted into NaN values

My database retrieves data from a time series, indicating the milliseconds an object spends in various states within an hour. The format of the data is as follows: { id: mejfa24191@$kr, timestamp: 2023-07-25T12:51:24.000Z, // This field is dynamic ...

Using Spring 3.0 with Jackson: How to post a composite entity using AJAX and JSON

Currently, I am utilizing spring 3.0 along with ajax and JSON in my work. The main domain class that I have is as follows: public class WebSite { int id; String description; SimpleType type; //getters and setters ... //... } The SimpleType class ...

Showcase multiple examples of three.js on a single webpage

I need to showcase several 3D objects on my web app within different containers. Currently, I'm creating multiple three.js renderers, each for a separate container. However, I encountered an error message: "WARNING: Too many active WebGL contexts. Old ...

Enhancements to managing universal configuration object across the entire application

My current project involves working on an application with multiple products. To streamline product-specific configuration and eliminate the need for excessive if-else statements, I am looking to implement product-specific config keys that are consistently ...

Before displaying the rows stored in the controller, ng-repeat initially displays one row

I am experiencing an issue with my back end service sending data to a $scope variable. I am using this variable to populate rows in a table with ng-repeat. Upon loading the page, initially one row is visible on the browser but then disappears once the loa ...

Converting JSON data into an array of a particular type in Angular

My current challenge involves converting JSON data into an array of Recipe objects. Here is the response retrieved from the API: { "criteria": { "requirePictures": true, "q": null, "allowedIngredient": null, "excluded ...

What are the alternatives to invoking a server-side C# method from JavaScript without using a WebMethod or UpdatePanel?

I am looking for alternatives to using an update panel. The common WebMethod approach is causing errors with the code below: private string currentHtml() { StringWriter str_wrt = new StringWriter(); HtmlTextWriter html_wrt = new Htm ...

The art of defining PropTypes for the style attribute in Reactjs

Is there a way to pass the 'style' attribute into my component using JSX syntax? <InputTextWithValidation id="name" style={{width:'100%'}} .../> I'm wondering how I should define the PropTypes for ...

Change the controller's classes and update the view in Angular

In my angular application, I have a popup window containing several tabs. These tabs are styled like Bootstrap and need to be switched using Angular. The code for the tabs is as follows (simplified): <div class="settingsPopupWindow"> <div> ...

What is the reason behind utilizing arrow functions in React event handlers?

function ButtonIncrement(){ const [count,setCount] = useState(0); render(){ <div> <h3> <button onClick={() => setCount(count+1)}>Increase count for amusement</button> <p>Total C ...

Creating dynamic keys using Typescript and JSON data format

Currently, I am developing an application using Typescript and React Native. Within my app, I have a JSON file containing information about poker hands that needs to be accessed. The structure of the JSON data is as follows: { "22": [ [ ...

Hide the background when the modal appears

I have successfully implemented a jQuery CustomBox modal on my website. However, I am facing an issue with hiding the content div behind the modal once it pops up. My goal is to make the content div reappear after the modal has been closed. You can view a ...