我试图弄清楚如何从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)是我返回的承诺。没有?
请阅读事务集()
的文档-它不返回承诺。这可能会使Firestore SDK感到困惑,因为您返回的是一组不是承诺的东西的promise.all()
。所以它可能认为您返回了一个错误。
您可能根本不需要从事务处理程序函数返回任何东西。只需调用set()
并完成它。如果希望通过runTransaction返回的promise将该值传递给runTransaction的调用方,则只需要从事务处理程序返回一些内容。
顺便说一句,在第一个示例中,不应该将承诺收集到在处理程序函数外部定义的数组中。如果事务处理程序运行了多次,这可能会导致问题。正如我链接到的文档所说:
不要修改事务函数中的应用程序状态。这样做会引入并发问题,因为事务函数可以多次运行,并且不能保证在UI线程上运行。
事务外部的数组将被视为“应用程序状态”,因为它不在函数本身内部。