Reputation: 23
I have a simple function that calls a firestore collection and returns a list of companies. I iterate through the list and output the company name. Once it's complete, I want to write "done".
function getCompanies() {
firestore.collection('companies')
.listDocuments()
.then(companies => {
for(var i in companies) {
companies[i].get().then(company => {
console.log(company.name);
});
}
}).catch(err => {
console.error(err);
});
};
getCompanies();
console.log('done');
In reality, this is what happens...
done
ford
gm
toyota
jeep
vw
I've looked into promises...
function getCompanies() {
firestore.collection('companies')
.listDocuments()
.then(companies => {
let promises = [];
for(var i in companies) {
companies[i].get().then(company => {
promises.push(doIt(company.id));
});
}
Promise.all(promises)
.then((results) => {
console.log("All done", results);
})
.catch((e) => {
// Handle errors here
});
}).catch(err => {
console.error(err);
});
};
function doIt(value) {
return new Promise((resolve) => {
setTimeout(() => {
console.log(value);
resolve(value);
}, Math.floor(Math.random() * 1000));
});
}
getCompanies();
But that didn't work either...
All done []
ford
gm
toyota
jeep
vw
Any pointers or advice? I feel like I'm forgetting to do something obvious :/.
Thanks in advance!
Upvotes: 0
Views: 72
Reputation: 690
This is a great overview of promises which explains which blocks of code are asynchronous.
https://levelup.gitconnected.com/async-await-vs-promises-4fe98d11038f
If you want 'done' to print in the correct order it must be called within the async block.
If I understand correctly, .get() returns a promise so you would need to do something like this.
function getCompanies() {
firestore
.collection('companies')
.listDocuments()
.then(companies => {
const myPromisesArr = companies.map(i => i.get());
Promises.all(myPromisesArr).then(companies => {
companies.forEach(company => {
console.log(company.id);
});
});
})
.catch(error => console.error(error))
.finally(() => console.log(`done`));
}
Upvotes: 0
Reputation: 12552
That is because the console.log
is synchrnous and getCompanies() is asynchrnous. The getCompanies will resolve in the future. Read up on Promise and async/await a bit.
A quick fix without using async/await will be:
function getCompanies() {
return firestore.collection('companies')
.listDocuments()
.then(companies => {
const promises = [];
for(var i in companies) {
promises.push(companies[i].get());
}
return Promise.all(promises);
}).catch(err => {
console.error(err);
});
};
Now to run the getCompanies
and console.log
in order, you need to execute the console.log after getCompanies resolve
getCompanies()
.then((companiesarr)=>{
companiesarr.forEach((c)=>{
console.log(c.name)
})
}).then(()=>console.log('done'))
Upvotes: 4
Reputation: 7770
You need to return the proimse from your function like this
function getCompanies() {
return firestore.collection('companies')
.listDocuments()
.then(companies => {
for(var i in companies) {
companies[i].get().then(company => {
console.log(company.name);
});
}
}).catch(err => {
console.error(err);
});
};
Upvotes: 0