lele2001
lele2001

Reputation: 1

How to return promises in a loop without exiting the loop?

I've got this admittedly very messy Firebase function.

exports.getAverage = functions.firestore
    .document('users/{userId}/days/{day}')
    .onUpdate((snapshot, context) => {
        let averages = {};
        let temp = [];
        let dayRefDoc = admin.firestore().collection(`users/${context.params.userId}/days`)
        return dayRefDoc.get().then(inner => {
            console.log(inner.docs);
            for (doc of inner.docs) {
                console.log(doc);
                return doc.ref.collection('session').get().then(session => {
                    session.docs.forEach(doc => temp.push(parseInt(doc.data().duration)))
                })
            }
        }).then(() => {
            console.log(temp);
            averages["sessionTime"] = (temp.reduce(function (a, b) { return a + b; }, 0)) / temp.length;
            return admin.firestore().collection('users').doc(context.params.userId).get().then(inner => {
                return inner.ref.update({ averageSessionTime: averages.sessionTime })
            })
        })
    })

The idea here is that each user in my database has a subcollection of days and each day has a subcollection called session. I want to go through each session document across all days and count up a variable called duration, then get the average of all durations across all sessions across all days.

Getting the average isn't difficult. I'm struggling with promises right now. Particularly, getting the function to iterate over every days subcollection on a particular user. My solution right now works for the first document it iterates over, but doesn't fetch the next, presumably because doc.ref.collection('session').get().then() is a promise of its own, and I'm running a return on this promise which causes it to break out of the for (doc of inner.docs) loop.

Am I correct in thinking that this is the issue? I feel like using a loop to create these promises is a bad idea anyway, so what would be the intended practice for doing something like this?

Upvotes: 0

Views: 35

Answers (1)

simirimia
simirimia

Reputation: 419

I thing you're on the right track. My first idea:

let docs = [];
for (doc of inner.docs) {
            console.log(doc);
            docs.append( doc.ref.collection('session').get() )
}
Promise.all(docs).then( values => {...} );

So you would collect all promises in a list, wait for all promises to be resolved and the do whatever you like on the results.

Upvotes: 0

Related Questions