I have users following categories. If a new product is added to the database, I want it to be automatically added to their wishlist through a cloud function.
I've been struggling for 2 days on that and no success :( The problem is with the fetch that returns an empty value. I understand from this thread that it has to do with async await but I did not manage to transform my function accordingly (which has to be v8 and not modular)
Thanks for your help guyz!
Here is my function :
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
exports.addProductToUserWhenCreated = functions.firestore.document('products/{documentUid}').onCreate((snap, context) => {
// get the categories of the product (array of category iDs, noting that a product can be in different categories)
let productCategories = snap.data().categories
let productId = snap.id
let categorySelectedBy
// For each category,
for (const category of productCategories) {
// get the selectedBy field (array of userIds) => HERE IS THE ISSUE
const snap = db.doc(`categories/${category}`).get()
snap.then((doc) => {
return categorySelectedBy = doc.data().selectedBy;
})
// Add the productId to the user's selectedProducts (by creating a subcollection in the user's document)
categorySelectedBy.map(user => {
db.doc(`users/${user}/selectedProducts/${productId}`).set({
achievedRate: 0,
})
})
}
});
I think you're pretty close. Because you use a for...of
loop, you can actually use await
if you mark the entire Cloud Function as async
:
// Add async here 👉 👇
exports.addProductToUserWhenCreated = functions.firestore.document('products/{documentUid}').onCreate(async (snap, context) => {
// get the categories of the product (array of category iDs, noting that a product can be in different categories)
let productCategories = snap.data().categories
let productId = snap.id
let categorySelectedBy
// For each category,
for (const category of productCategories) {
// get the selectedBy field (array of userIds)
// await here 👇
const doc = await db.doc(`categories/${category}`).get()
const categorySelectedBy = doc.data().selectedBy;
// Add the productId to the user's selectedProducts (by creating a subcollection in the user's document)
// 👇 Use Promise.all to wait for all writes here
Promise.all(categorySelectedBy.map(user => {
return db.doc(`users/${user}/selectedProducts/${productId}`).set({
achievedRate: 0,
})
}))
}
});