Running Async Tasks in Parallel
An await statement waits for one Promise before continuing.
If several asynchronous operations do not depend on each other, waiting for them one by one may be slower than necessary.
Instead, you can start all the operations at the same time and wait for them together.
Sequential Operations
When each operation depends on the previous one, use multiple
await statements.
Example
async function loadData() {
let response1 = await fetch("customer.json");
let customer = await response1.json();
let response2 = await fetch("products.json");
let products = await response2.json();
let text = "";
text += JSON.stringify(customer);
text += JSON.stringify(products);
}
// Call the async load function
loadData();
response.json()
response.json()) is a built-in method of the Fetch API.
It reads a raw HTTP response stream, parses the JSON text, and resolves as a completed JavaScript object or array that you can actually use in your code.
Independent Operations
If asynchronous operations are independent, they can start at the same time.
This is called running tasks in parallel.
Example 1
async function loadData() {
let customerPromise = fetch("customer.json");
let productsPromise = fetch("products.json");
let customer = await customerPromise;
let products = await productsPromise;
let text = "";
text += JSON.stringify(customer);
text += JSON.stringify(products);
}
// Call the async load function
loadData();
All three downloads begin immediately.
The await statements wait only when the results are needed.
Example 2
async function loadData() {
let customerPromise = fetch("customer.json");
let productsPromise = fetch("products.json");
let customer = await customerPromise;
let products = await productsPromise;
let text =
"<h3>Customer</h3>" +
customer.name + ", " +
customer.city +
"<h3>Products</h3>" +
products[0].name + ", " +
products[1].name + ", " +
products[2].name;
}
// Call the async load function
loadData();
Promise.all()
The Promise.all() method waits for several Promises to complete.
It returns a single Promise that resolves when every Promise has been fulfilled.
Example
async function loadData() {
let responses = await Promise.all([
fetch("customer.json"),
fetch("products.json"),
fetch("news.json")
]);
}
// Call the async load function
loadData();
Reading JSON Responses
You can combine Promise.all() with response.json().
Example
async function loadData() {
let responses = await Promise.all([
fetch("customer.json"),
fetch("products.json"),
fetch("news.json")
]);
let data = await Promise.all(
responses.map(response => response.json())
);
}
// Call the async load function
loadData();
Promise.all() Errors
If one Promise is rejected, the Promise returned by Promise.all() is also rejected.
Example
async function loadData() {
try {
let data = await Promise.all([
fetch("missing1"),
fetch("missing2"),
fetch("missing3")
]);
}
catch(err) {
myDisplayer(err.message);
}
}
// Call the async load function
loadData();
Note
fetch() does not reject its Promise for HTTP errors such as 404 Not Found.
It resolves with a Response object.
To make Promise.all() reject on HTTP errors, check response.ok and throw an error yourself.
Example
async function getFile(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(response.status + " " + response.statusText);
}
return response.text();
}
// async function to load data
async function loadData() {
try {
let data = await Promise.all([
getFile("missing1"),
getFile("missing2"),
getFile("missing3")
]);
}
catch(err) {
myDisplayer(err.message);
}
}
// Call the async load function
loadData();
The example above demonstrates both Promise.all() and proper error handling.
Promise.allSettled()
The Promise.allSettled() method waits until every Promise has finished.
Unlike Promise.all(), it does not stop when one Promise is rejected.
Example
fetch("a.txt"),
fetch("b.txt"),
fetch("missing.txt") ]);
Each result contains a status of fulfilled or rejected.
Promise.any()
The Promise.any() method returns the first fulfilled Promise.
Rejected Promises are ignored unless every Promise is rejected.
Example
fetch("server1/data"),
fetch("server2/data"),
fetch("server3/data")
]);
Promise.race()
The Promise.race() method returns the first Promise that settles.
The first Promise may be fulfilled or rejected.
Example
fetch("server1/data"),
fetch("server2/data")
]);
Which Method to Use?
| Method | Waits For | Typical Use |
|---|---|---|
Promise.all() |
All fulfilled | Load everything |
Promise.allSettled() |
All settled | Accept failures |
Promise.any() |
First fulfilled | Fastest successful response |
Promise.race() |
First settled | Timeouts and competitions |
| Method | Fails if one rejects? | Returns |
|---|---|---|
Promise.all() | Yes | Array of values |
Promise.allSettled() | No | Array of result objects |
Promise.any() | Only if all reject | First fulfilled value |
Promise.race() | If the first settles with rejection | First settled result |
Summary
- Use sequential
awaitstatements when one operation depends on another. - Start independent asynchronous operations together whenever possible.
- Use
Promise.all()when every operation must succeed. - Use
Promise.allSettled()when you want every result, even if some fail. - Use
Promise.any()when you need the first successful result. - Use
Promise.race()when you need the first Promise that settles.