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 to load data
async function loadData() {
let response1 = await fetch("customer.json");
let customer = await response1.json();
let response2 = await fetch("products.js");
let products = await response2.json();
let text = "";
text += JSON.stringify(customer);
text += JSON.stringify(products);
}
// Call the async load function
loadData();
Try it Yourself »
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 to load data
async function loadData() {
let customerPromise = fetch("customer.js");
let productsPromise = fetch("products.js");
let customer = await customerPromise;
let products = await productsPromise;
let text = "";
text += JSON.stringify(customer);
text += JSON.stringify(products);
}
// Call the async load function
loadData();
Try it Yourself »
All three downloads begin immediately.
The await statements wait only when the results are needed.
Example 2
// async function to load data
async function loadData() {
let customerPromise = fetch("customer.js");
let productsPromise = fetch("products.js");
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();
Try it Yourself »
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 to load data
async function loadData() {
let responses = await Promise.all([
fetch("customer.json"),
fetch("products.json"),
fetch("news.json")
]);
}
// Call the async load function
loadData();
Try it Yourself »
Reading JSON Responses
You can combine Promise.all() with response.json().
Example
// async function to load data
async function loadData() {
let responses = await Promise.all([
fetch("customer.js"),
fetch("products.js"),
fetch("news.js")
]);
let data = await Promise.all(
responses.map(response => response.json())
);
}
// Call the async load function
loadData();
Try it Yourself »
Promise.all() Errors
If one Promise is rejected, the Promise returned by Promise.all() is also rejected.
Example
// async function to load data
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();
Try it Yourself »
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 to get file
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();
Try it Yourself »
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
let results = await Promise.allSettled([
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
let fastest = await Promise.any([
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
let result = await Promise.race([
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.