Wanderlust project: Fetching a photo using async-await (step 43)

Hi community!

I’m trying to complete the last step (43) of the last project ‘Wanderlust’ of the JavaScript course. In particular this:

For a real challenge, try fetching venue photos! This will require an additional request for venue details for each venue, as the photo information is not returned in the initial request.

So I have 2 async functions:

Async function: getVenues
const getVenues = async () => {
  const city = $input.val();
  const urlToFetch = `${url}?${near}${city}&${limit}&client_id=${clientId}&client_secret=${clientSecret}&${version}`;
  try{
    const response = await fetch(urlToFetch);
    if(response.ok){
      const jsonResponse = await response.json();
      const venues = jsonResponse.response.groups[0].items.map(e => e.venue); //extract venues out of response
      return venues;      
    }
  } catch(error){console.log(error.message);}  
};

This function gets a certain amount of venues using the inserted city name from the Foursquare API. These venue objects don’t have much details (API response): id, name, location.

To get a photo of the venue I used the ‘details’ response from the API. This response has the property ‘bestPhoto’ with the prefix & suffix to the photo I want to use.

To get the details I made this function:

Async function: getVenueDetails
const getVenueDetails = async id => {
    const urlToFetch = `${url2}${id}?client_id=${clientId}&client_secret=${clientSecret}&${version}`;
    try{
      const response = await fetch(urlToFetch);
      if(response.ok){
        const jsonResponse = await response.json();
        const details = jsonResponse.response.venue;
        return details;
      } 
    } catch(error){console.log(error.message);}          
};

This gets the details of a specified venue (with the id).

Now I need to accomplish this:

  1. Get the venues of the inserted city
  2. Get the ID’s of the venues
  3. Get the details of the ID’s of the venues
  4. Pass the details to a render function to show the wanted info on the website (unfinished, but added on the bottom)

I’m stuck at passing the details to the render function:

  getVenues()
  .then(async venues => {
    const details = [];
    for(let i = 0; i <venues.length; i++){ //Can't use forEach
      await details.push(getVenueDetails(venues[i].id));
    }
    return renderVenues(details);
  });

If I log the ‘details’ after the loop this contains 3 pending Promise-objects.
So it looks like the for-loop doesn’t wait on the getVenueDetails().

So here’s my question: How can I loop through the result of a async-function and pass that result to another async function?

Googling got me more confused about looping & async/await. Some say it’s impossible, others say you can’t use .forEach.
I have to feeling I’m making this more complex than it is. So all help is appreciated &
thank you in advance!

renderVenues(data)
const renderVenues = (venues) => {
  console.log('Render');
  console.log(venues);
  console.log(venues.forEach(v => v.value.bestPhoto));
  $venueDivs.forEach(($venue, index) => {
    // Add your code here:
    const ven = venues[0];
    console.log(ven);
    const venueIcon = ven.categories[0].icon;
    const venueImgSrc = `${venueIcon.prefix}bg_64${venueIcon.suffix}`;
    console.log('RENDER');
    console.log(venue);
    let venueContent = createVenueHTML(ven.name, ven.location, venueImgSrc);
    $venue.append(venueContent);
  });
  $destination.append(`<h2>${venues[0].location.city}</h2>`);
};

Mystery solved.

I was awaiting the ‘details.push’ instead of the async function ‘getVenueDetails’.

WRONG
await details.push(getVenueDetails(venues[i].id));
WORKS
details.push(awaits getVenueDetails(venues[i].id));

After hours of rewriting the code I can finish this project & this course!