提问者:小点点

必须返回promise的firebase事务


我试图弄清楚如何从angular 6/typescript应用程序向firebase数据库编写事务。

下面是我使用的一个工作示例作为指导:

const transactions = [];

return db.runTransaction(function(transaction) {
            // const promises = [];
            descriptionsInDB.forEach(dbDescription => {
                if (dbDescription.matched === false) {
                    // item wasn't found, so add the item to the transaction.
                    const phraseItem: PhrasesDB = {
                        query: dbDescription.description,
                        updatedAt: Date.now(),
                        createdAt: Date.now(),
                        workflows: {
                            [workflowId]: true
                        }
                    };
                    const newPhrasesRef = phrasesCol.doc();
                    transactions.push(transaction.set(newPhrasesRef, phraseItem));
                } else {
                    if (dbDescription.data.workflows && dbDescription.data.workflows[workflowId]) {
                        // do nothing, this phrase is already part of the record.
                    } else { // update the workflows that are part of the record.
                        const workflows = { 
                            workflows: {
                                [workflowId]: true
                            }
                         };
                        const phrasesRef = phrasesCol.doc(dbDescription.dbId);
                        transactions.push(transaction.update(phrasesRef, workflows));
                    }
                }
            });

            return Promise.all(transactions); 
        })

我确定的关键部分如下:

1)创建一个数组来保存事务:const transactions=[];

2)开始事务:返回db.runtransactions(function(transactions){…

3)使用事务:transaction.set(newPhraseRef,phraseItem)执行DB查询;

4)将查询返回的事务推送到事务数组:transactions.Push(transaction.set(newPhraseRef,phraseItem));

5)用事务数组返回一个承诺:Return promission.all(transaction);

如果我有这个权利,那么我应该能够将这个公式应用到我正在尝试编写的事务中,并且它应该能够工作:

        const pendingRef = `Pending/${req.query.inviteId}`;
        const acceptance = {
          'cryptoInvitationAcceptance': req.body.cryptoInvitationAcceptance,
          'reason': (req.body.reason !== undefined ? req.body.reason : '')
        }
return db.runTransaction(function(t) {
          const transArray = [];
          const docRef = db.collection('Pending').doc(req.query.inviteId);
          transArray.push(t.set(docRef, acceptance));
          return Promise.all(transArray);
        }).then(result => {
          console.log('result = ', result);
        }).catch(err => {
          console.log('err = ', err);
        });

但它总是转到catch块并打印出消息:

err=错误:您必须在transaction()-回调中返回一个承诺。

但我是在回报一个承诺,不是吗?行:return promission.all(transArray)是我返回的承诺。没有?


共1个答案

匿名用户

请阅读事务集()的文档-它不返回承诺。这可能会使Firestore SDK感到困惑,因为您返回的是一组不是承诺的东西的promise.all()。所以它可能认为您返回了一个错误。

您可能根本不需要从事务处理程序函数返回任何东西。只需调用set()并完成它。如果希望通过runTransaction返回的promise将该值传递给runTransaction的调用方,则只需要从事务处理程序返回一些内容。

顺便说一句,在第一个示例中,不应该将承诺收集到在处理程序函数外部定义的数组中。如果事务处理程序运行了多次,这可能会导致问题。正如我链接到的文档所说:

不要修改事务函数中的应用程序状态。这样做会引入并发问题,因为事务函数可以多次运行,并且不能保证在UI线程上运行。

事务外部的数组将被视为“应用程序状态”,因为它不在函数本身内部。