DEV Community

Rocktim Saikia
Rocktim Saikia

Posted on

Async function behaves differently in loop [SOLVED]

I have very basic async function going on here. my primary function "formatData" is formatting some data from an array "users" . which are basically some github usernames.

This function formats the data in this way :

[
  { name: 'rocktimsaikia', followers: 12 },
  { name: 'aholachek', followers: 90 },
  { name: 'benawad', followers: 30 }
]
Enter fullscreen mode Exit fullscreen mode

Very basic . But the issue is to get the followers count i created another async function "getFollowers" which extracts the followers count with given argument which is the github user name that i am providing in formatData.

Here is my code :

const getFollowers = async name => {
  const data = await fetch(`https://api.github.com/users/${name}`);
  const { followers } = await data.json();
  return followers;
};

const formatData= async () => {
  const users = ["rocktimsaikia", "aholachek", "benawad"];
  const result = await users.map(async (user) => ({
      name: user,
      followers: await getFollowers(user)
   }));
  return result;
};
Enter fullscreen mode Exit fullscreen mode

But the function formatData() returns everything with a promise. What am i missing here ? please help !

Top comments (6)

Collapse
 
bharath_bheemireddy profile image
Bharath_Bheemireddy

Try this one.



const formatData= async () => {
  const users = ["rocktimsaikia", "aholachek", "benawad"];
  let result = [];
  for(let i = 0; i < users.length; i++) {    
      let followers = await getFollowers(users[i]);
      result.push({
        name: users[i],
        followers: followers
      })
  }
  return result;
};
Collapse
 
rocktimsaikia profile image
Rocktim Saikia

That makes sense and works just fine. Thanks 🎉 but is there anyway to do it with map.

Collapse
 
bharath_bheemireddy profile image
Bharath_Bheemireddy

If you want to use with map, you have to wrap with Promise.all()



formatData= async () => {
  const users = ["rocktimsaikia", "aholachek", "benawad"];
  const result = Promise.all(users.map(async (user) => ({
      name: user,
      followers: await getFollowers(user)
   })));
  return result;
};
Thread Thread
 
brnkrygs profile image
Brian Krygsman

(and you might want to await that Promise.all())

Thread Thread
 
bharath_bheemireddy profile image
Bharath_Bheemireddy • Edited

Promise.all() waits for all fulfillments (or the first rejection).
developer.mozilla.org/en-US/docs/W...

Thread Thread
 
brnkrygs profile image
Brian Krygsman

You're exactly right... and it does so by returning a Promise itself.

Since it returns a Promise, it's await-able in the context of an async function like the code here.

Depends on the expectations of the calling code of course, but if the calling code is expecting the value as opposed to the Promise, it might be worth considering an await

e.g.

//...
const result = await Promise.all(users.map(async (user) => ({
//...