Suppose I have the following Firestore data structure:
collection tickets
{
name: "Testticket",
open: true,
users: [
"users/abcdefg1234" // Firestore reference
]
}
collection users
{
name: "John Doe",
color: "green"
}
My goal is to get all the tickets where open
is true, including the user object istead of the reference.
Currently I am doing this:
// Firebase Functions node.js code
async function getUserData(item) {
const queryResult = await item.get();
return await queryResult.data();
}
exports.getOpenTickets = async (request, response) => {
const query = await db.collection("tickets").where("open", "==", true).get();
let tickets = [];
query.forEach(async (doc) => {
let data = doc.data();
console.log("data", data);
data.userObjects = await Promise.all(data.users.map(getUserData));
console.log("data.userObjects", data.userObjects);
tickets.push(data);
});
return response.json(tickets);
};
Problem: The user data is fetched but the main function is not waiting for it (checked with console log statements).
This is my node.js console log:
i functions: Beginning execution of "api"
! Google API requested!
- URL: "https://oauth2.googleapis.com/token"
- Be careful, this may be a production service.
> data {
> open: true,
> name: 'Testticket',
> users: [
> DocumentReference {
> _firestore: [Firestore],
> _path: [ResourcePath],
> _converter: [Object]
> }
> ]
> }
i functions: Finished "api" in 1069.554ms
> data.userObjects [ { color: 'green', name: 'John Doe' } ]
How to fix this?
CodePudding user response:
If you want to run asynchronous operations within a loop, then you should not use forEach
. Try refactoring the code using for of
loop as shown below:
exports.getOpenTickets = async (request, response) => {
const snap = await db.collection("tickets").where("open", "==", true).get();
let tickets = [];
for (const doc of snap.docs ) {
let data = doc.data();
console.log("data", data);
data.userObjects = await Promise.all(data.users.map(getUserData));
console.log("data.userObjects", data.userObjects);
tickets.push(data);
}
return response.json(tickets);
};
Also checkout Using async/await with a forEach loop.