Reputation: 249
I have the following loop that is fetching data and then store it into the allVegetables
variable. I need the loop to finish before I can log the length of the array. With the below code I get zero for the length of allVegetables
var allVegetables = [];
for (var i = 0; i < 10; i++) {
//fetch the next batches of vegetables
fetch(`https://www.nofrills.ca/api/category/NFR001001002000/products?pageSize=48&pageNumber=${i}&sort=title-asc`, {
"headers": {
...
},
"referrer": "https://www.nofrills.ca/Food/Fruits-%26-Vegetables/Vegetable/c/NFR001001002000?sort=title-asc",
"referrerPolicy": "no-referrer-when-downgrade",
"body": null,
"method": "GET",
"mode": "cors"
}).then(
function (response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
return;
}
response.json().then(function (data) {
//ad the results of the data to the array
allVegetables = allVegetables.concat(data.results);
});
})
};
console.log("number of vegetables are:", allVegetables.length);
Currently the logs give me zero which I assume it is because it is not waiting for the loop to finish filling up the array allVegetables
. I also assume I should use async but I am a newbie and cant figure out how to do this
Upvotes: 0
Views: 578
Reputation: 20924
Try to store all the fetch requests, and their results in an array. This will result in an array of promises. With these promises you can wait for all of the to finish with Promise.all
and handle the output of all the responses in a single go and store them all in the allVegetables
variable.
Because you'll end up with an array of array use Array.prototype.flat()
to create a single array with all the values which you can assign to your allVegetables
variable.
let allVegetables = [];
let iterations = 10;
const requests = Array(iterations).fill().map((_, i) => fetch(`https://www.nofrills.ca/api/category/NFR001001002000/products?pageSize=48&pageNumber=${i}&sort=title-asc`, {
"headers": {
...
},
"referrer": "https://www.nofrills.ca/Food/Fruits-%26-Vegetables/Vegetable/c/NFR001001002000?sort=title-asc",
"referrerPolicy": "no-referrer-when-downgrade",
"body": null,
"method": "GET",
"mode": "cors"
}).then(response => {
if (response.status !== 200) {
throw new Error('Looks like there was a problem with request ${i}. Status Code: ' + response.status);
}
return response.json();
}).then(data => {
return data.results;
});
const responses = Promise.all(requests).then(data => {
allVegetables = [...allVegetables, ...data.flat()];
}).catch(error => {
console.log(error);
});
Upvotes: 1
Reputation: 529
You could store all your fetch promises inside an array and then use Promise.allSettled to wait for them to finish their work.
Here is a quick example:
const responses = [];
for (let i = 0; i < 4; i++) {
responses.push(
fetch("https://jsonplaceholder.typicode.com/posts/1").then(response =>
response.json()
)
);
}
Promise.allSettled(responses).then(console.log);
That will log an array of objects with this shape:
{
status: 'string',
value: Object
}
Being the 'value' attribute the one containing the information retrieved from the fetch.
In your case you would simply have to check the length of your array.
You can check the example on a sandbox.
Upvotes: 0