Sequential vs Concurrent Awaiting
Placing independent `await` expressions one after another can make asynchronous operations wait in sequence, while starting multiple Promises before awaiting them lets their work overlap. The distinction matters when operations do not depend on one another.
An `async` function can pause at each `await` until the awaited Promise settles. If you start the second operation only after the first `await` finishes, the two operations are effectively serialized even when they are independent.
To allow independent operations to overlap, create both Promises first and then await their results. `Promise.all()` is a common way to wait for several Promises together and receive their results in input order.
Concurrency does not mean that JavaScript runs these operations simultaneously on the same thread. Instead, asynchronous work can make progress through the runtime, browser APIs, network stack, or other facilities while the JavaScript thread is available for other work.
Sequential awaiting is appropriate when the second operation needs the result of the first, or when intentionally controlling ordering. Concurrent awaiting is useful for independent tasks such as fetching unrelated resources.
Key points
- Sequential `await`s can serialize independent asynchronous operations.
- Start independent Promises before awaiting them to permit overlap.
- `Promise.all()` waits for multiple Promises and preserves input order in its result array.
- Concurrent asynchronous work is not the same as parallel JavaScript execution.
- Use sequential awaiting when later work depends on an earlier result.
Interview questions
What is the difference between sequential and concurrent `await`?
With sequential awaiting, the function waits for one Promise before starting the next operation if that operation is created afterward. With concurrent awaiting, independent Promises are created first, allowing their asynchronous work to overlap. `Promise.all()` can then wait for all of them together. This can reduce total latency when the operations are independent.
Why can `Promise.all()` be faster than two sequential `await`s?
If two operations each take roughly the same amount of time and neither depends on the other, sequential awaiting makes their waiting periods add together. Starting both Promises first lets their asynchronous work overlap. The combined wait is then approximately the duration of the slower operation. The exact timing depends on the underlying operations and runtime conditions.
Does `Promise.all()` execute Promises in parallel?
`Promise.all()` itself does not execute work; it observes Promises that have already been created or supplied to it. The underlying asynchronous operations may overlap, depending on what they are and how the environment handles them. JavaScript execution on the main thread is not thereby converted into parallel execution. For network requests in a browser, for example, the browser can handle I/O while JavaScript waits for completion.
When should you not use concurrent awaiting?
You should not start operations concurrently when a later operation requires the result of an earlier one. For example, if a request needs an identifier returned by another request, the dependency requires sequential control flow. Sequential execution can also be intentional when ordering, rate limits, or resource constraints matter. The goal is not maximum concurrency, but correct and efficient coordination.