0

Disclaimer: This is my first question, and I am new to JavaScript.

I am attempting to populate some html text elements by fetching data using an API. This API returns a JSON object with some of the text I need, but also with some API URLs I need to then fetch additional data from. Some of these URLs are held in arrays. So, I need to fetch a JSON object, iterate through it while sometimes storing strings and sometimes fetching additional JSONs that hold the remainder of the text I need. I am having a lot of trouble dealing with promises and the asynchronous execution. I don't know how to wait for a promise to be completed, so the returned data keeps coming up undefined.

async function GetData(address) {
    const response = await fetch(address);
    const json = await response.json();
    return json;
}
async function CleanData(origData) {
    Object.entries(origData).forEach(async ([key,value]) => {
        // look for arrays
        if (Array.isArray(value)) {
            value.forEach(async (element, i) => {
                // look for links inside arrays
                if (element.indexOf("https") != -1) {
                    let newData = await GetData(element);
                    // replace link with name or title
                    if (newData["name"] !== undefined) {
                        origData[key][i] = newData["name"]
                    } else if (newData["title"] !== undefined) {
                        origData[key][i] = newData["title"];
                    }
                }
            });
        }
        // look for links and replace with name
        if (value.indexOf("https") != -1) {
            let newData = await GetData(value);
            origData[key] = newData["name"];
        }
    })
    return origData;
}
function PopulateFields(fieldData) {
    nameId.innerText = fieldData["name"];
    valueIds.forEach(node => {
        const nodeId = node.id;
        node.innerText = fieldData[nodeId];
    });
}
document.getElementById("button").addEventListener(
"click", async () => {               // also tried without async using .then()
    let data = await GetData(ApiUrl);
    data = await CleanData(data);           
    PopulateFields(data);
}

1 Answers1

0

Switch to normal loops (for...of) instead of forEach. It will likely solve all your problems. There's never a good reason to use forEach, it's just a holdover from the jQuery days.

The issue now is that you pass async functions to forEach(), but there's no way to await those. By using regular loops you can just await inside the loop and the 'correct' thing will happen.

Evert
  • 93,428
  • 18
  • 118
  • 189