How Do I call an API inside a for loop and then fill data with the response?

Hello there, I know there are some topics out there about calling an api inside a loop but I´ve read them and it looks they are not asking exactly about my issue.

What I am trying to do is make a program to get all the repositories of GitHub of a given user. I do have a function that does that successfully.

await fetch(`https://api.github.com/users/${RANDOM_USER}/repos`)
  .then(res => {
    if (res.status >= 400) {
      throw new Error("Bad response from server");
    }
    return res.json();
  })
  .then(repo => {
    repositories = repo
  })
  .catch(err => {
    console.error(err);
  });

The function returns something like this on a console.log loop:

function getRepos (data) {
  for (const key in data) {
      console.log(`Repository: ${data[key].name}`);
  }    
}

console.log(getRepos(repositories))

Outputs:

Repository: random_application
Repository: random_application2

I wanted to complicated a little bit more, and so I want now to get all the commits of each repository of that given user. The function will output on a console in the following format: (I hope somebody can confirm with me that this is indeed possible):

Repository: random_application, commits: { Object with commit info of that repository}
Repository: random_application2, commits: { Object with commit info of that repository}

I have come up with the following function so far:

function getCommits (repositoryData) {
  for (const key in repositoryData) {
       let emptyObjectWithCommits = {}
          fetch(`https://api.github.com/repos/Onpointiscake/${repositoryData[key].name}/commits`)
        .then(res => {
          if (res.status >= 400) {
            throw new Error("Bad response from server");
          }
          return res.json();
        })
        .then(repo => {
          //console.log(repo)
          emptyObjectWithCommits = repo
        })
        .catch(err => {
          console.error(err);
        })
    console.log(`Repository: ${repositoryData[key].name}, commits: ${emptyObjectWithCommits.commit}`)
  }
}

Here’s the problem, as you can see the console.log will be executed before the api call, so I tried putting “await” before “fetch”. However if I do that Node gives me an error of “unexpected reserved word”.

¿Any ideas please? I´ve been 2 whole days stuck on this function and I think it can really be done this way.

What’s biting you is that Promises are asynchronous. I see two possibilities;

  1. Set the promise returned by each fetch...then into an array, and use Promise.all() to await them all. MDN has great documentation on that one.

  2. If you get comfortable with it, consider using the github graphql API - in a single request, you get exactly the info you’re looking for. Both repos and commits in a single pass. GitHub GraphQL API - GitHub Docs

Either works, and should solve the issue.

I’m not sure I understand, is the problem just the console log? Why can’t you just log out inside the promise chain?

The function needs to be async if you want to use await.

Just for my curiosity. You say node gives you an error, so are we to understand it’s a node app using node fetch or what?