javascriptfirebasegoogle-cloud-firestoreasync-awaitfor-await

Firebase Functions - Unexpected `await` inside a loop - Cannot read property 'reduce' of undefined


I am using Firebase Functions to pull in user data. Because there is a "IN" query limit of 10 for Firestore queries, I have to run an async callout in a loop.

I can't do an async callout in a loop so I have to push the callouts synchronously into an array and then call await Promise.all() to run the callouts outside of the loop.

When I do this, I receive an error from Firestore

TypeError: Cannot read property 'reduce' of undefined

I can see that the results value is a Promise. So I must be writing the reduce or the Promise.all() incorrectly...

If I can see the value is a promise, why is the promise coming in as undefined?

const buildChatMatches = async ({id, matches, singles}) => {
  const existing = singles || {};
  if (Array.isArray(matches) && matches.length > 0) {
    let numberOfDozens = matches.length / 10;
    let results = [];
    let i = 0;
    while (i < Math.ceil(numberOfDozens)) {
      let sliceMatches = matches.slice(i * 10, (i + 1) * 10);
      const query = admin
        .firestore()
        .collection(USER_COLLECTION_NAME)
        .where("id", "in", sliceMatches);
      results.push(query.get());
      i++;
    }
    let allResults = await Promise.all(results);
    return allResults.docs.reduce((map, doc) => {
      map[doc.id] = pickUserInfo(doc.data(), existing[doc.id]);
      return map;
    });
  }
  return {};
};

thanks to Doug's answer:

let allResults = await Promise.all(results);
allResults.forEach(function(querySnapshot) {
  for (let i in querySnapshot.docs) {
    users.push(querySnapshot.docs[i]);
  }
});

Solution

  • allResults is going to be an array of QuerySnapshot objects. It will not have a property called docs, because it's just an array. Since it doesn't have a property called docs, allResults.docs will be undefined, and will not have a method called reduce.

    You will have to somehow iterate or map that array of QuerySnapshot objects so that you can access the docs on each individual snapshot.