I created an array using some data then I tried to copy it to the useState array. But it doesn’t work. Also, I viewed it using the console log. but line 49 logged before line 36. can I fix this?
Console -
Code -
const retrieveCompany = async () =>{
try{
const colletionRef = collection(db, 'corporations');
const q = query(colletionRef, orderBy('createdAt', "desc"));
const unsub = onSnapshot ( q,(snapshot) => {
setCorporations([]);
let list = [];
snapshot.docs.forEach( async (doc) => {
let newItem = {id: doc.id, ...doc.data()};
if(newItem.poc) {
let userData = await getDoc(newItem.poc);
console.log(userData.data())
newItem = {pocUser: userData.data(), ...newItem}
console.log(newItem);
list.push(newItem);
}
else{
list.push(newItem);
}
// await getPOSUser(doc.data().poc);
// list.push({ id: doc.id, ...doc.data()});
})
console.log(list)
setCorporations(list);
console.log(corporations)
});
return () => {
unsub();
}
}catch(err){
console.log(err);
}
}
You’re using an async callback inside the forEach(), but forEach() itself is not asynchronous. So the list
will always be empty on line 50.
You probably want to use a combination of Promise.all() and map().
Let me know if you would like to see an example.
1 Like
@colinthornton please Can you give an example?
Let’s say you have a list of IDs ids
.
Let’s say you have an asynchronous function fetchDocument
that takes a single ID, and returns a promise that evaluates to some data.
Let’s say you want to fetch the document for every ID in the list and then log the entire list of documents.
That could look like this:
const ids = [1, 2, 3, 4, 5];
const docs = await Promise.all(
ids.map(async (id) => {
const doc = await fetchDocument(id);
return doc;
})
);
console.log(docs);
1 Like
You could also use a for of
loop:
const ids = [1, 2, 3, 4, 5];
const docs = [];
for (const id of ids)
const doc = await fetchDocument(id);
docs.push(doc);
)
console.log(docs);
As with @colinthornton suggestion, both of these code samples must be put into an async function to work.
I feel I should point out that there is one big difference to these two approaches though. With Promise.all() the fetches will be run at the same time in parallel. With await inside a for loop it will run sequentially, waiting for the first fetch to finish before starting the second, waiting for that to finish before moving onto the third, and so on. In theory, the parallel processing with Promise.all() should run faster so I would prefer it when parallelization is possible.
This is true regarding speed. The one disadvantage of the Promise.allapproach is that if any of the requests fail, the promise fails immediately. With my approach, you would get some data and know which ones failed (to be able to fetch again). It really depends on the application I suppose.
Side Note: The number of concurrent requests is limited by the browser, so if the number of requests made is more than 10 on Chrome (last I read), then the concurrency advantage becomes less of a speed factor the greater the number over 10 becomes.
1 Like
And sometimes you need sequential processing in which case Promise.all() is out, so @ravinduonline take notes, you’ll probably end up using both of these methods in your career.
(getting sidetracked here but…) Also, this is a pretty new API but they recently added Promise.allSettled() which works similarly but waits for all promises to finish, whether they succeed or fail. Haven’t got a chance to use it yet though.
2 Likes