0

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,
      })
    })
  }
});

1 Answer 1

1

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,
      })
    }))
  }
});
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so much Puff. I wouldn't have found out the solution by myself. I owe you one! (and i'll dig into the Promise.all to understand id :p

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.