0

I am building a project website which uses the rawg api to fetch data about games and displays them on the screen. I have also implemented a search functionality. My function getGame is using the base url which is called API_URL. My problem is that the data returned by this link does not return description as one of its variables. It has other stuff like game id and game name etc but no description. I have checked the docs and it says that in order to get the details of a game i need to use a different fetch link which takes in id as a parameter. So i implemented another function called getDescription() which takes in an id from the games.forEach function. I am able to console log all the descriptions of the games that are being displayed. My question is how would i be able to insert the description into the dom inside my showGames function. My code is attached below. Thanks.

const API_URL = `https://api.rawg.io/api/games?key=${apiKey}&page=5&page_size=40`;
const SEARCH_API = `https://api.rawg.io/api/games?key=${apiKey}&search="`;
const form = document.getElementById('form');
const search = document.getElementById('search-game');
const main = document.getElementById('main');

getGames(API_URL)
async function getGames(url){
  const request = await fetch(url)
  const response = await request.json()
  showGames(response.results)
}

async function getDescription(id){
  const request = await fetch(`https://api.rawg.io/api/games/${id}?key=${apiKey}`)
  const response = await request.json();
  showDescription(response.description)
}

function showGames(games){
  main.innerHTML = '';
  games.forEach(game => {
    const { background_image, name, released, rating_top, id } = game;
    const gameEl = document.createElement('div');
    const platform = game.parent_platforms.map(platform => platform.platform.name).join(', ');
    getDescription(id)
    gameEl.classList.add('card');
    gameEl.innerHTML = `
    <div class="card-top">
      <img src="${background_image}" alt="" class="card-image">
    </div>
    <div class="card-bottom">
    <div class="card-info">
      <h1 class="game-name">${name}</h1>
      <h3>Release date: ${released}</h3>
      <p>Platforms: <span>${platform}</span></p>
      <p>*****I WANT TO ENTER THE DESCRIPTION HERE*****</p>
    </div>
      <div class="card-rating">
        <span class="${getColorByRating(rating_top)}">${rating_top}</span>
      </div>
    </div>
    `;
    main.appendChild(gameEl);
  })
}

Edit Here is my console log for response inside getDescription function Console log

I was able to get my wanted output by adding async right after my forEach like this games.forEach(async game => {....}) Here is my working code

const API_URL = `https://api.rawg.io/api/games?key=${apiKey}&page=5&page_size=40`;
const SEARCH_API = `https://api.rawg.io/api/games?key=${apiKey}&search="`;
const form = document.getElementById('form');
const search = document.getElementById('search-game');
const main = document.getElementById('main');

getGames(API_URL)
async function getGames(url){
  const request = await fetch(url)
  const response = await request.json()
  showGames(response.results)
}

async function getDescription(id){
  const request = await fetch(`https://api.rawg.io/api/games/${id}?key=${apiKey}`)
  const response = await request.json();
  return response;
}

function showGames(games){
  main.innerHTML = '';
  games.forEach(async game => {
    const { background_image, name, released, rating_top, id } = game;
    const gameEl = document.createElement('div');
    const platform = game.parent_platforms.map(platform => platform.platform.name).join(', ');
    const response = await getDescription(id)
    gameEl.classList.add('card');
    gameEl.innerHTML = `
    <div class="card-top">
      <img src="${background_image}" alt="" class="card-image">
    </div>
    <div class="card-bottom">
    <div class="card-info">
      <h1 class="game-name">${name}</h1>
      <h3>Release date: ${released}</h3>
      <p>Platforms: <span>${platform}</span></p>
      <p>${response.description}</p>
    </div>
      <div class="card-rating">
        <span class="${getColorByRating(rating_top)}">${rating_top}</span>
      </div>
    </div>
    `;
    main.appendChild(gameEl);
  })
}
jmoerdyk
  • 5,544
  • 7
  • 38
  • 49
CodeItNow
  • 41
  • 1
  • 6
  • Could you please edit your post and show the implemention of `showDescription` function – Zulfiqar Ali May 03 '22 at 15:03
  • Hi, thats the thing i don't know what my showDescription function should look like in order for it to be able to add the description in the games.forEach loop. – CodeItNow May 03 '22 at 15:06
  • Ok then, can you tell me what type of data does `getDescription` function returns, is it just a `string` or a `json object` with `description` key and a `string` value? – Zulfiqar Ali May 03 '22 at 15:13
  • It just returns a string – CodeItNow May 03 '22 at 15:15
  • Please don't vandalize your posts. By posting on the Stack Exchange network, you've granted a non-revocable right, under the [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/) license, for Stack Exchange to distribute that content (i.e. regardless of your future choices). By Stack Exchange policy, the non-vandalized version of the post is the one which is distributed, and thus, any vandalism will be reverted. If you want to know more about deleting a post please see: [How does deleting work?](https://stackoverflow.com/help/what-to-do-instead-of-deleting-question). – jmoerdyk May 05 '22 at 15:58

2 Answers2

0

As you said that getDescription function just returns a string, so you can do something like this

async function getDescription(id){
  const request = await fetch(`https://api.rawg.io/api/games/${id}?key=${apiKey}`)
  const response = await request.json();
  //showDescription(response.description)
  //instead of using a function, just return the response from this func
  return response
}

function showGames(games){
  main.innerHTML = '';
  games.forEach(game => {
    const { background_image, name, released, rating_top, id } = game;
    const gameEl = document.createElement('div');
    const platform = game.parent_platforms.map(platform => platform.platform.name).join(', ');
    //save response into a variable
    const response = getDescription(id)
    gameEl.classList.add('card');
    gameEl.innerHTML = `
    <div class="card-top">
      <img src="${background_image}" alt="" class="card-image">
    </div>
    <div class="card-bottom">
    <div class="card-info">
      <h1 class="game-name">${name}</h1>
      <h3>Release date: ${released}</h3>
      <p>Platforms: <span>${platform}</span></p>
      <p>${response.description}</p>
    </div>
      <div class="card-rating">
        <span class="${getColorByRating(rating_top)}">${rating_top}</span>
      </div>
    </div>
    `;
    main.appendChild(gameEl);
  })
}

Then use that variable response.description in the html string literal

Zulfiqar Ali
  • 269
  • 1
  • 3
  • 12
  • Sorry i think i misunderstood your last question about what getDescription returns. In my getDescription function if i just do showDescription(response) then it returns various json objects with their respective key and values. One of these keys is description. Since i am not interested in other stuff i was do showDescription(response.description) which was giving me what i needed. Your solution gives me this now [object Promise]. – CodeItNow May 03 '22 at 15:27
  • can you show us the output of `console.log(response)` inside your `getDescription` function – Zulfiqar Ali May 03 '22 at 15:29
  • I have updated my question with your request – CodeItNow May 03 '22 at 15:35
  • I've updated my code, it should work fine now – Zulfiqar Ali May 03 '22 at 15:39
  • I am getting undefined as my output now – CodeItNow May 03 '22 at 15:42
  • You will get undefined as forEach doesn't wait the promise to resolve as I mentioned in my answer. – Spetty May 03 '22 at 15:51
  • Did you resolve it? – Spetty May 04 '22 at 10:53
0

You should be able to save the response of showDescription in a variable and then include it in your inner Html.

What it struggle with this is the fact that if array.forEach has a callback that returns a promise (like the async showDescription()), the javascript engine will not wait it to be resolved or rejected, so console will show an error that description is null.

There is a nice question where you can find how to loop promises here

You have to update getDescription like this:

async function getDescription(id){
  const request = await fetch(`https://api.rawg.io/api/games/${id}?key=${apiKey}`)
  const response = await request.json();
  return response.description;
}

edit showGames like this

async function showGames(games) {
...

and use for inside showGames

 for (const game of games) {
    const description = await getDescription(game.id)
...
  }

Every loop will wait getDescription() to be completed before start the next loop

Spetty
  • 93
  • 2
  • 13