1

The purpose of this code is to use a local JSON file with objects like this:

[{playerName: 'BobbyLee', "totalPoints": 0, "games" : [ {"gameId": 1, "pointsScored": 0}, {"gameId": 2, "pointsScored": 0} ]}, {playerName: 'MaryJane', "totalPoints": 0, "games" : [ {"gameId": 1, "pointsScored": 0}, {"gameId": 2, "pointsScored": 0} ]}]

And then map the JSON array and use axios/cheerio to retrieve 'pointsScored' data like this:

  let updatedData = (JSONDATA.map( player => {
    let games = player.games;
    games.map( game => {
      // This function retrieves 'pointsScored' for each game
      async function retrieve(gameId) {
 
        const resp = await axios.get(BASE_URL)
          .then(res => {
            // This gets the unique URL for the game
            const $ = cheerio.load(res.data)
            const sectionContent = bContent.find(gameId);
            const gamePage = sectionContent.attr('href');
            // This function uses the unique URL to get 'pointsScored'
            async function secondLevel(url) {
              const resp1 = await axios.get(url)
                .then(res => {
                  const $ = cheerio.load(res.data)
                  const table = $('table[id=player_table]');
                  const rows = table.children('tbody');
                  const row = rows.children('tr');
                  const points = row.children('[data-stat=points_scored]');
                  const ret = points.html().toString();
                  game.pointsScored = ret; // update 'pointsScored'
     
                  return;
                }).catch(err => console.error(err));
            }
            secondLevel(gamePage); // calls the other async function 
          
       }).catch(err => console.error(err));
      }

      retrieve(game.gameId);

    }));
  
  // Process the data with updated 'pointsScored'.
  processData(updatedData);
}));

Once the scores are updated, I planned on processing that new data. However, when I run the code processData function is initialized before all data are fetched.

The code block above is also wrapped by an async function that is called in an useEffect block.

D.D
  • 11
  • 1
  • 1
    You use `map()` twice but don’t return anything from them. That smells like a problem from the start – Sami Kuhmonen Sep 04 '22 at 17:16
  • 1
    Why for each game you load the *same* BASE_URL? Seems like it would give the same response every time, so why not just do that part once? – trincot Sep 04 '22 at 18:38
  • If you can provide the `BASE_URL` it'd be easier to validate a solution. But the general problem is that `map`/`forEach` doesn't block on async. You'll need `Promise.all` or a `for...of` loop. See [Using async/await with a forEach loop](https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop). The inner `retrieve(gameId)` and `secondLevel(gamePage)` that are never awaited abandon yet more promise chains into the void. The rule with promises is you have to `await` or `then` each and every promise in the chain between the call and where you want to consume the result. – ggorlen Sep 05 '22 at 20:27

0 Answers0