Fetching data from Airtable using JavaScript but variables stay empty

Issue with JavaScript fetch and Airtable integration

I’m trying to retrieve survey data from Airtable and display it on my webpage, but I’m running into problems. The fetch request seems to work and I can see the data in the console, but my DOM elements aren’t getting updated with the retrieved information.

I think the problem is that my variables aren’t being properly assigned with the data from Airtable. When I try to display the content, nothing shows up on the screen even though the API call appears successful.

Here’s what I’m working with:

(function() {
    window.addEventListener('load', function() {
        
        document.getElementById('continue').addEventListener('click', function() {
            window.location.href = 'survey2.html';
        })
        
        let quest1 = document.getElementById('question1');
        let quest2 = document.getElementById('question2');
        let quest3 = document.getElementById('question3');
        let quest4 = document.getElementById('question4');
        let quest5 = document.getElementById('question5');
        
        let surveyId = 1;
        
        let fetchSurveyData = function() {
            fetch('https://api.airtable.com/v0/app123ABC/Survey', {
                method: 'GET',
                headers: {
                    'Authorization': 'Bearer key123XYZ'
                }
            })
            .then(response => response.json())
            .then(data => {
                console.log(data)
                
                for(let i = 0; i < data.records.length; i++) {
                    let record = data.records[i];
                    
                    if(surveyId === record.fields.survey_id) {
                        let q1_data = record.fields.Question1;
                        let q2_data = record.fields.Question2;
                        let q3_data = record.fields.Question3;
                        let q4_data = record.fields.Question4;
                        let q5_data = record.fields.Question5;
                        
                        quest1 = q1_data;
                        quest2 = q2_data;
                        quest3 = q3_data;
                        quest4 = q4_data;
                        quest5 = q5_data;
                        
                        console.log(quest1);
                    }
                }
            })
        }
        
        fetchSurveyData();
        
        function displayQuestion() {
            let paragraph = document.createElement('p');
            paragraph.innerHTML = quest1;
            document.getElementById('question1').appendChild(paragraph);
        }
        
        document.getElementById('question1').innerHTML = displayQuestion()
    })
})();

Any ideas why the variables aren’t getting populated correctly?

Yeah, everyone’s spot on about the async timing, but you’re overcomplicating this. Manual DOM manipulation for API stuff is a nightmare to maintain and debug.

I hit the same wall building survey flows for our product team. Instead of fighting fetch promises and DOM updates, I just automated everything with Latenode. You can pipe Airtable straight to your webpage - no JavaScript headaches.

Set up a workflow that grabs survey data from Airtable and dumps it on your frontend automatically. No more async timing issues, variable mess, or DOM wrestling. Data just shows up where you want it.

When your survey changes or you need filtering, just tweak the workflow instead of debugging JS. Much cleaner.

Check it out: https://latenode.com

Had the same issue with external APIs last year. You’re reassigning your DOM element variables instead of updating their content. When you do quest1 = q1_data, you’re overwriting the HTML element reference with just a string. Your displayQuestion() function doesn’t return anything, so innerHTML = displayQuestion() sets it to undefined. You’re also trying to append to an element you’re about to overwrite. Here’s what works: keep your DOM references as-is, but in your fetch callback, directly update with quest1.innerHTML = record.fields.Question1 (or textContent if you don’t need HTML formatting). Ditch the separate display function and handle everything in the promise chain where you actually have the data.

you’ve got an issue with how you assign the values. Instead of quest1 = q1_data, try using quest1.textContent = q1_data. this ensures you update the element’s content instead of just changing the var value.

The main issue is timing. Your displayQuestion() function runs immediately when the page loads, but the fetch request is asynchronous. You’re trying to display data that hasn’t arrived yet.

I hit this exact problem a few years back building a dashboard that pulled metrics from our database. Move your display logic inside the fetch promise.

Here’s the fix:

fetch('https://api.airtable.com/v0/app123ABC/Survey', {
    method: 'GET',
    headers: {
        'Authorization': 'Bearer key123XYZ'
    }
})
.then(response => response.json())
.then(data => {
    for(let i = 0; i < data.records.length; i++) {
        let record = data.records[i];
        
        if(surveyId === record.fields.survey_id) {
            quest1.textContent = record.fields.Question1;
            quest2.textContent = record.fields.Question2;
            quest3.textContent = record.fields.Question3;
            quest4.textContent = record.fields.Question4;
            quest5.textContent = record.fields.Question5;
            break; // exit loop once found
        }
    }
})

Ditch that separate displayQuestion() function entirely. Just update the DOM elements directly inside the promise after you get the data back.

Also remove the line document.getElementById('question1').innerHTML = displayQuestion() at the bottom. It’s running before your data arrives anyway.

Your code has two main issues I ran into when I first built API integrations. First, you’re overwriting your DOM element references with strings - when you do quest1 = q1_data, you lose the connection to the actual HTML element. Second, your fetch is async but you’re trying to use the data outside the promise like it’s synchronous.

Here’s the fix: update the DOM elements directly inside your fetch promise using the original references. Change those variable assignments to quest1.textContent = record.fields.Question1 and so on. Ditch the displayQuestion() function entirely - it’s just adding confusion. The key thing to remember: async operations need to be handled where the data actually exists, inside the promise chain.