如何在循环中返回承诺而不退出循环?

时间:2020-04-11 14:03:13

标签: javascript asynchronous promise

我确实拥有这个非常混乱的Firebase函数。

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

这里的想法是我数据库中的每个user都有一个days的子集合,并且每天都有一个名为session的子集合。我想整天浏览每个session文档,并计算一个名为duration的变量,然后获取整天所有会话的所有持续时间的平均值。

获得平均值并不困难。我现在正在兑现诺言。特别是,使函数可以迭代特定用户的每个days子集合。我的解决方案现在适用于迭代的第一个文档,但无法获取下一个文档,大概是因为doc.ref.collection('session').get().then()是它自己的承诺,而我正在对该承诺进行回报,这导致它被破坏在for (doc of inner.docs)循环之外。

我是否正确地认为这是问题所在?我觉得使用循环创建这些承诺反而是一个坏主意,那么做这样的事情的预期做法是什么?

1 个答案:

答案 0 :(得分:0)

我认为您的目标正确。我的第一个想法:

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

因此,您将在列表中收集所有诺言,等待所有诺言得到解决,然后对结果执行任何您想做的事情。

相关问题