2

I want to construct an object from multiple promise results. The only way to do this is something like this:

const allPromises = await Promise.all(asyncResult1, asyncResult2);
allPromises.then([result1, result2] => {
  return {result1, result2};
})

A nicer way (especially when more data is being constructed) would be this, with the major drawback of the async requests happening one after the other.

const result = {
  result1: await asyncResult1(),
  result2: await asyncResult2(),
}

Is there a better way to construct my object with async data I am waiting for?

2
  • In your first code block, asyncResult1 and asyncResult2 appear to be variables that contain promises (presumably for things that have already started). But in your second code block, you're calling them and using the result of calling them as promises. Which is it in your real code? (Also note that you're missing [] around what you're passing Promise.all.) Commented Oct 16, 2019 at 13:35
  • Fair comment about the [] missing, the examples above are more meant to explain my question. Commented Oct 16, 2019 at 15:00

1 Answer 1

1

See my comment, it's a little unclear what asyncResult and asyncResult2 are, because your first code block uses them as though they were variables containing promises (presumably for things already in progress), but your second code block calls them as functions and uses the result (presumably a promise).

If they're variables containing promises

...for processes already underway, then there's no problem with awaiting them individually, since they're already underway:

const result = {
    result1: await asyncResult1, // Note these aren't function calls
    result2: await asyncResult2,
};

That won't make the second wait on the first, because they're both presumably already underway before this part of the code is reached.

If they're functions

...that you need to call, then yes, to call them both and use the results Promise.all is a good choice. Here's a tweak:

const result = await Promise.all([asyncResult1(), asyncResult2()])
                    .then(([result1, result2]) => ({result1, result2}));

One of the rare places where using then syntax in an async function isn't necessarily the wrong choice. :-) Alternately, just save the promises to variables and then use the first option above:

const ar1 = asyncResult1();
const ar2 = asyncResult2();
const result = {
    result1: await ar1,
    result2: await ar2,
};
Sign up to request clarification or add additional context in comments.

4 Comments

Ok agreed, the idea of sending the async request on it's way and then await for the result when constructing the object is a good idea. The 'on-its-way' idea is an important concept, thank you.
I would add that it can actually be better to return a promise even if the async functions are already underway, because the caller may have more async functions to initiate before waiting for a response. In that case, using this Promise.all call (with asyncResult instead of asyncResult()) is still the best solution! (Thanks for the example!)
@mltsy - (You're welcome!) I'm not sure what you mean above...?
Sorry - I think I was confused about the original question. I was just pointing out that in some cases it is better to return Promise.all... rather than awaiting it, so that the caller of your function can decide when to await. But in this case, that would likely complicate the interface unnecessarily (returning an object populated with results is much more straight-forward than returning an object populated with promises! But if that optimization is useful, you could contain the complexity by returning a class, containing promises, with getters that await the promises!)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.