0

I'm doing a little data analysis from chess.com data

I have this code

const getUsernames = async function() {
  let response = await chessAPI.getCountryPlayers('RE')
  names = [...response.body.players]
  //console.log(names)
  return names
}

const grabPlayerScores = async function() {
  let players = getUsernames()
  // let playerStats = [];
  for (i = 0; i = players.length; i++) {
    let data = await chessAPI.getPlayerStats(i)
    console.log(data)
  }
}

grabPlayerScores();

I can't get the other function to await the return of the first. I know I should use promises or structure my other function differently but I'm still getting the hang of these types of functions.

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Wells
  • 55
  • 7
  • 5
    You need `let players = await getUsernames()` – Barmar Oct 05 '21 at 19:50
  • Does this answer your question? [How to return the response from an asynchronous call](https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call) – Heretic Monkey Oct 05 '21 at 20:02

3 Answers3

1

You need to add another await in your grabPlayerScores function to wait for getUsernames to finish.

const grabPlayerScores = async function() {
  // Add an 'await' here
  let players = await getUsernames();

  for(let i = 0; i = players.length; i++) {
    let data = await chessAPI.getPlayerStats(i)
    console.log(data)
  }
}
Robert Stefanic
  • 401
  • 1
  • 4
  • 17
1

I changed bit in your code,

const grabPlayerScores = async function () {
  let players = await getUsernames();
  for (i = 0; i = players.length; i++) {
    let data = await chessAPI.getPlayerStats(players[i]);
    console.log(data)
  }
}
SaminatorM
  • 630
  • 5
  • 18
1

As a best practice, you should make sure all of your functions return a value. Use const for variables that will not change, and let for variables that you absolutely will change. Watch out for name = ... where you didn't write const or let, as this makes names into a global -

const getUsernames = async function() {
  const response = await chessAPI.getCountryPlayers('RE')
  return response.body.players // <- probably no need to copy
}
const grabPlayerScores = async function() {
  const players = await getUsernames()
  return Promise.all(players.map(p => chessAPI.getPlayerStats(p)))
}

Now grabPlayerScores will be a promise containing an array of all player scores -

grabPlayerScores().then(console.log).catch(console.error)
[ ..., ... ,... ]

Maybe you want the player data combined with the score data in the final output?

const grabPlayerScores = async function() {
  const players = await getUsernames()
  return Promise.all(players.map(async p => ({
    player: p,
    scores: await chessAPI.getPlayerStats(p)
  })))
}
grabPlayerScores().then(console.log).catch(console.error)
[ { player: "alice", scores: ... },
  { player: "brenda", scores: ... },
  { player: "catherine", scores: ... } ]

Another good practice is to make your functions take parameters. This makes them more reusable in other areas of your program -

const getUsernames = async function(countryCode) {
  const response = await chessAPI.getCountryPlayers(countryCode)
  return response.body.players
}

const grabPlayerScores = async function(countryCode) {
  const players = await getUsernames(countryCode)
  return Promise.all(players.map(async p => ({
    player: p,
    scores: await chessAPI.getPlayerStats(p)
  })))
}

Now you pass "RE" as an argument to your function, allowing you to easily reuse this function for other countries -

grabPlayerScores("RE").then(console.log).catch(console.error)
Mulan
  • 129,518
  • 31
  • 228
  • 259