0

I feel like I'm missing something very basic here... The summary is that I have an array of 10 cards which correspond to 10 different collections on my website. Each card has an image element. I want to replace that card with a new card where the image's source and a few other items have changed (and also I've added animations).

The problem is that my fetch for the new image source, which I grab from another site (website/collectionName/configs.ini) is only working for the last card in the loop.

let cardsOnly = document.createElement("div");
cardArray = document.querySelectorAll('.cards');
cardArray.forEach(function(card) {
    //do a bunch of stuff to the card like add title and remove old classes
    card.appendChild(cardTitleDiv);
    collectionName = //grabbed from this page
    bgImage = document.createElement("img");
    let configWebsite = website/collectionName/configs.ini

    const request = async () => {
        const response = await fetch(configWebsite)
        const text = await response.text() //so now I have the text from the config website
        newImgSource = //extracted from text
        console.log(collectionName + " " + newImgSource);
        bgImage.setAttribute("src", newImgSource);
        console.log(bgImage);
        card.appendChild(bgImage);
    }
    request();
    //do a bunch of other stuff to the card like add description div
    card.appendChild(descriptionDiv);
    cardsOnly.appendChild(card); //add all cards to cardsOnly div
}
//append the cardsOnly div to my wrapper on the page. 

When the page loads, the cards all have the correct titles, the correct descriptions, and here's the weird part... the first console.log, for each of the 10 cards in the array, this DOES output the CORRECT collectionName AND the CORRECT new image source which I just fetched and extracted....

but when I look inside the cardsOnly div, the only card in there with an <img> element is the last card. And the console.log(bgImage) that's inside request()... well that keeps outputting the <img> element that corresponds to the last (10th) card.


My console looks like this:

collection1: correct new image source for collection 1
<img> element for collection 10 with correct img src for collection 10

collection2: correct new img src for collection 2
<img> element for collection 10 with correct img src for collection 10

etc..
etc.. 

Why is this happening?

James B
  • 432
  • 5
  • 22
  • The `request` is async but you never await it. Please consult [this](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call). – Wiktor Zychla Sep 03 '19 at 16:30

1 Answers1

2

Possibly a scoping problem. bgImage is never declared and has therefore function scope like variables declared with var. That means you are working on the same bgImage in every iteration. You should use let so you get block scope.

let bgImage = document.createElement("img");
Holli
  • 5,072
  • 10
  • 27
  • Progress! This actually created all the image elements accurately... it just put all of them on the last card. I'll try to refactor and hopefully this was all that I messed up – James B Sep 03 '19 at 17:06
  • That's probably because of the async. You are doing `card.appendChild(cardTitleDiv);` within the loop body, but you add the next element within the async function. So what happens is you are adding n divs first, until the async function runs, and then you add n images to the last div. You should do both within the function. – Holli Sep 03 '19 at 17:26
  • So within request() I only do the fetch for the source and set the src attribute for bgImage, then I append the image after I call request() and everything seems to work fine. Thank you SO MUCH for the help! Your original answer basically fixed everything :D – James B Sep 03 '19 at 18:46