首页 > 解决方案 > 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) 开始事务:return db.runTransactions(function(transaction) {…</p>

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

4)将查询返回的交易推送到交易数组:transactions.push(transaction.set(newPhraseRef,phraseItem));

5)返回一个带有事务数组的promise:return Promise.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()-callback 中返回一个 Promise。

但我正在回报一个承诺,不是吗?这行:return Promise.all(transArray) 是我要返回的承诺。不?

标签: typescriptfirebasepromisetransactionsangular6

解决方案


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

您可能根本不需要从事务处理函数返回任何内容。只需打电话就set()可以了。如果你想通过它返回的承诺将该值传递给 runTransaction 的调用者,你只需要从你的事务处理程序返回一些东西。

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

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

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


推荐阅读