Recent chats
ASKGEEZ Q&A GUIDETechnology & devices

How can I avoid awaiting independent work one request at a time?

Quick answer

If two asynchronous operations do not depend on each other, start both before waiting for their results, then await Promise.all with their promises. This lets the operations proceed concurrently, and the results come back in the same order as the promises in the array. Keep awaits sequential when the second operation needs a value produced by the first.

LET’S WORK THROUGH IT

The question, the details, the next step.

Question

I have two asynchronous operations in JavaScript. They do not use each other’s results, but I’ve written await for the first and then await for the second. How can I avoid making them wait one at a time?

Geez

Call both operations first, then await their promises together with Promise.all. For example, if loadProfile() and loadMessages() are independent:

const profilePromise = loadProfile();
const messagesPromise = loadMessages();

const [profile, messages] = await Promise.all([
  profilePromise,
  messagesPromise
]);

The operations are started when their functions are called; Promise.all waits for the promises you give it. Its results are arranged to match the input order, so profile corresponds to the first promise and messages to the second. [S1]

By contrast, this waits for the first result before calling the second function:

const profile = await loadProfile();
const messages = await loadMessages();

That sequence is appropriate if the second operation needs the first result, or if you deliberately want to start it later. The key distinction is dependency, not simply how many await keywords appear.

Follow-up question

Could you show the difference side by side? I want to make sure I’m not accidentally changing what the operations do.

Geez

Assuming both functions return promises and loadMessages() does not need the profile, these versions express different scheduling:

// Sequential: call the second function after the first settles
const profile = await loadProfile();
const messages = await loadMessages();
// Concurrent: call both before waiting for their results
const [profile, messages] = await Promise.all([
  loadProfile(),
  loadMessages()
]);

In the second version, JavaScript calls each function to obtain its promise, then Promise.all waits for the promises together. [S1] The values are still available for use in the same way. Keep the order in the array matched to the names on the left: swapping the array entries swaps which result is assigned to each variable.

This lets independent work proceed at the same time; it does not mean either operation itself becomes faster. The relevant guidance does not establish how long a particular operation will take, whether it will succeed, or whether a particular service or function is safe to run alongside another.

Follow-up question

What if the second operation needs a value from the first? For example, I need an account ID before I can load that account’s details.

Geez

That is a real dependency, so keep those steps sequential. First obtain the ID, then pass it to the details operation:

const account = await loadAccount();
const details = await loadDetails(account.id);

The second operation cannot be correctly called until you have the ID it needs. The decision rule is: if you cannot correctly call the second operation until you have the first result, await the first before starting the second. If both operations can be called with information already available, start them and await their promises together. [S1]

Follow-up question

Can you give me a practical way to decide which pattern to use when I’m reviewing a function?

Geez

For each await, ask what information is required to start the next operation. If the required inputs are already available, and the operations are intended to proceed independently, collect their promises and use Promise.all. If an input comes from an earlier result, keep that dependency sequential.

For example, suppose a page needs a list of projects and the current user’s preferences, and neither request needs the other’s result. Treat that as independent work:

const [projects, preferences] = await Promise.all([
  loadProjects(),
  loadPreferences()
]);

If loading a project’s tasks requires a project ID returned by loadProject, preserve the order:

const project = await loadProject();
const tasks = await loadTasks(project.id);

One other behavior matters: Promise.all rejects if an input promise rejects. [S1] Decide how your surrounding code should handle that failure rather than assuming both operations will always succeed.

A practical checklist

  • List the asynchronous operations and the inputs each one needs.

  • Mark whether any operation needs a value returned by another.

  • Start independent operations before awaiting their combined results.

  • Keep dependent steps sequential and pass the earlier result explicitly.

  • Check that the Promise.all result order matches the variables receiving it.

  • Decide how the surrounding code should handle a rejected promise.

A few more useful answers

Does `Promise.all` start the operations for me?

Call each operation to obtain its promise, then pass those promises to Promise.all. Calling the functions obtains the promises; Promise.all waits for them together. [S1]

Does `Promise.all` return results in the order operations finish?

No. Its result order matches the order of the promises in the input array, not their completion order. [S1]

Should I use `Promise.all` if one operation depends on another?

Not for that dependency: await the first result, then use it to start the next operation. Use Promise.all for operations that can be started independently.

Sources

References used for this guide.

  1. [S1] Promise.all() — JavaScript | MDN
    developer.mozilla.org · Checked

YOUR QUESTION. YOUR DETAILS.

Let’s work through your situation.

Get a tailored answer or help with your next task. Starts at $1, with a quote before you pay.

Ask your own question
← Back to Geez at Work