2

In my react app I have some user ids and need to fetch their emails and names from different endpoints so what i do is:

const promises = ids.map(
   id => (  {email: axios.get(`blabla/${id}/email`), name: axios.get(`blabla/${id}/name`)}  )
);

and it gets me back:

[
{email: Promise, name: Promise},{email: Promise, name: Promise},{email: Promise, name: Promise},...
]

Now to get the data what i do is:

  const results = [];
  promises.map(({ email, name}) =>
      Promise.all([email, name]).then((result) => {
        results.push({
          email: result[0].data,
          name: result[1].data,
        });
      })
    );

but i have a feeling that it may not be a good way to it, i mean it works now but i don't want to get into any issues later !! haha, for instance, a race between promises, or for instance, a user email set for another user. I don't know if they are even possible to happen but I need to check with you experts that if you confirm this way or do you suggest something else.

2 Answers 2

1

It's fine other than that you're not using the array map creates. Any time you're not using map's return value, use a loop (or forEach) instead. Also, any time you're writing to an array you're closing over from asynchronous operation results, it sets you up to accidentally use that array before it's populated

In this case, though, I'd use the array map gives back:

Promise.all(
    promises.map(({ email, name}) =>
        Promise.all([email, name])
        .then(([email, name]) => ({email, name}))
    )
).then(results => {
    // ...use results here, it's an array of {email, name} objects
})
.catch(error => {
    // ...handle error here, at least one operation failed...
});
Sign up to request clarification or add additional context in comments.

2 Comments

thanks indeed for your answer, could you please explain a bit more about what you said: any time you're writing to an array you're closing over from asynchronous operation results, it sets you up to accidentally use that array before it's populated
@reactdeveloper - With the code in your question, if you used results in code immediately after the map call, it wouldn't have anything in it. More here: stackoverflow.com/questions/23667086/…
1

I'd be doing it like this.

const promises = ids.map(
   id => (  [axios.get(`blabla/${id}/email`), axios.get(`blabla/${id}/name`)]  )
);
Promise.all(promises.map(Promise.all).then(
    ([email, name]) => {
        console.log(email, name)
    }
)).then(values => {
    console.log(values);
});

2 Comments

thanks for your answer, could you explain it a bit more, for instance, this part: promises.map(Promise.all)
the map takes a callback and passes each entry on each interaction, so I passed Promise. All as the callback, where it takes an argument which is another array [email, name] and resolve it and return it to the map. It is the same as the answer above, except he defined the function then called Promise and I just passed the promise function directly.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.