Wait for Multiple Fetch Requests to Finish
Last updated: January 14, 2023.
To wait for multiple fetch requests to complete before doing something, first stores all of the requests inside an array.
In the fetch examples below, requests are being made for ficticious posts, comments and photos data from JSONPlaceholder, a free test API for fetching JSON data:
const array = [
fetch('https://jsonplaceholder.typicode.com/posts'),
fetch('https://jsonplaceholder.typicode.com/comments'),
fetch('https://jsonplaceholder.typicode.com/photos')
];
The native Promise
object constructor, which can be used to create new promises, also has methods available on it for handling multiple promises.
Since fetch is promise-based, we can use the Promise
objects method for handing multiple fetch requests.
To wait until all requests have resolved successfully before doing something, you can use Promise.all()
, passing in the array of fetch requests. Handle this like a regular promise and the output will be an array with three response objects.
Because the processing of the response objects with res.json()
also returns promises that need to be waited upon, you can use Promise.all()
to wait on them as well.
The final output will be an array of three JavaScript object containing the posts, comments and photos data.
Promise.all(array)
.then(responses => {
return Promise.all(responses.map(response => response.json()))
.then(data => {
console.log(data); // Array(3) [ (100) […], (500) […], (5000) […] ]
})
})
.catch(err => console.error("Multiple fetch failed"))
This solution is functional but involves nested promise-handling.
This can be avoided by creating an async
function instead and then using await
to wait upon promises to complete:
async function makeRequests() {
try {
const responses = await Promise.all(array);
const data = await Promise.all(responses.map(response => response.json()))
console.log(data); // Array(3) [ (100) […], (500) […], (5000) […] ]
} catch {
console.error("Multiple fetch failed");
}
}
makeRequests();
One potential issue with this solution is that if one fetch fails, the entire Promise.all()
will fail and trigger the catch block in the code below:
const array = [
fetch('https://jsonplaceholder.typicode.com/posts'),
Promise.reject(), // Simulates first fetch failing immediately
fetch('https://jsonplaceholder.typicode.com/photos')
]
async function makeRequests() {
try {
const responses = await Promise.all(array);
const data = await Promise.all(responses.map(response => response.json()))
console.log(data);
} catch {
console.error("Multiple fetch failed"); // Error message logs to console
}
}
makeRequests();
Avoiding 'fail-fast' behavioir
If you want to avoid the 'fail-fast' of Promise.all()
behavior, use Promise.allSettled()
instead.
Instead of returning an array of return values, Promise.allSettled()
returns an array of objects. Each object has a status property with a value of either 'fulfilled
' or 'rejected
'.
For promises (e.g. fetch requests) that are successfully fulfilled, a value
property also exists on the object containing the return value.
For rejected promises, a reason
property exists that may give more information on why the promise failed.
Adapted to the previous example, we can now get the values for fetch requests that succeed, even if one fails:
const array = [
fetch('https://jsonplaceholder.typicode.com/posts'),
Promise.reject(), // Simulates first fetch failing immediately
fetch('https://jsonplaceholder.typicode.com/photos')
]
async function makeRequests() {
try {
const responses = await Promise.allSettled(array);
// Handles array of fetch requests with Promise.allSettled()
const successArray = [];
responses.map(response => {
if (response.status === "fulfilled") {
successArray.push(response);
}
})
// Pushes only successfully fulfilled responses into successArray
const data = await Promise.allSettled(successArray.map(response => response.value.json()))
// Reads readable stream on body of responses in successArray to JS object (from JSON)
data.forEach(obj => console.log(obj.value))
// Logs values on objects (return values of successful fetches)
// Array(100) [ {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, … ]
// Array(5000) [ {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, … ]
} catch {
console.error("Multiple fetch failed");
}
}
makeRequests();
Related posts
- JSONPlaceholder test API (external link)
- Using fetch to make GET, POST, PUT and DELETE requests
- Using Fetch with async/await
- Resolve JavaScript promises sequentially
- A beginner’s guide to JavaScript promises
- Async/await: a modern syntax for asynchronous JavaScript