Typescript firebase事务您必须返回一个承诺
我试图弄清楚如何从angular 6/typescript应用程序将事务写入firebase数据库 下面是我作为指导使用的一个工作示例:Typescript firebase事务您必须返回一个承诺,typescript,firebase,promise,transactions,angular6,Typescript,Firebase,Promise,Transactions,Angular6,我试图弄清楚如何从angular 6/typescript应用程序将事务写入firebase数据库 下面是我作为指导使用的一个工作示例: const transactions = []; return db.runTransaction(function(transaction) { // const promises = []; descriptionsInDB.forEach(dbDescription => {
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(函数(事务){
3) 使用事务执行DB查询:transaction.set(newPhraseRef,phraseItem)
4) 将查询返回的事务推送到事务数组:transactions.Push(transaction.set(newPhraseRef,phraseItem))
5) 使用事务数组返回承诺:Return promise.all(事务)
如果我有这个权利,那么我应该能够将这个公式应用到我试图编写的事务中,并且它应该可以工作:
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=Error:必须在事务()回调中返回承诺
但是我正在返回一个承诺,不是吗?行:return promise.all(transArray)是我正在返回的承诺。否?请阅读文档-它不返回承诺。这可能会混淆Firestore SDK,因为您返回的是
promise.all()
一系列不是承诺的东西。因此,它可能认为您返回了一个错误
您可能根本不需要从事务处理程序函数返回任何内容。只需调用set()
并完成它。您只需要通过事务处理程序返回的承诺从事务处理程序返回某些内容
顺便说一句,在第一个示例中,您不应该将承诺收集到处理程序函数外部定义的数组中。如果事务处理程序多次运行,则可能会导致问题。正如我链接到的文档所述:
不要在事务函数内修改应用程序状态。
这样做将引入并发问题,因为事务
函数可以多次运行,并且不能保证在
用户界面线程
事务外部的数组将被视为“应用程序状态”,因为它不在函数本身内部。请阅读文档,因为它不返回承诺。这可能会混淆Firestore SDK,因为您返回的是
promise.all()
一系列不是承诺的东西。因此,它可能认为您返回了一个错误
您可能根本不需要从事务处理程序函数返回任何内容。只需调用set()
并完成它。您只需要通过事务处理程序返回的承诺从事务处理程序返回某些内容
顺便说一句,在第一个示例中,您不应该将承诺收集到处理程序函数外部定义的数组中。如果事务处理程序多次运行,则可能会导致问题。正如我链接到的文档所述:
不要在事务函数内修改应用程序状态。
这样做将引入并发问题,因为事务
函数可以多次运行,并且不能保证在
用户界面线程
事务外部的数组将被视为“应用程序状态”,因为它不在函数本身内部。事实证明,这是最好的方法:
return t.get(pendingDocRef).then(data => {
t.set(pendingDocRef, acceptance, {merge:true});
});
get(…)返回它要求的承诺,因此set(…)不必返回
我不喜欢这样。我仍然认为我应该能够自己在一个事务中进行设置(即没有get)
我还发现这类作品:
commit()还返回一个承诺,但随后我得到了一个非常奇怪的行为:事务一遍又一遍地重复自己,直到它进入catch块,并出现了一个“transaction has expired”的错误。然而,数据被提交到数据库中,因此如果您不介意错误(让它通过),commit()也可以工作
查看此帖子了解详细信息:事实证明,这是最好的方法:
return t.get(pendingDocRef).then(data => {
t.set(pendingDocRef, acceptance, {merge:true});
});
get(…)返回它要求的承诺,因此set(…)不必返回
我不喜欢这样。我仍然认为我应该能够自己在一个事务中进行设置(即没有get)
我还发现这类作品:
commit()还返回一个承诺,但随后我得到了一个非常奇怪的行为:事务一遍又一遍地重复自己,直到它进入catch块,并出现了一个“transaction has expired”的错误。然而,数据被提交到数据库中,因此如果您不介意错误(让它通过),commit()也可以工作
有关详细信息,请参阅本文:在您发布的示例中,
事务[]
用于从forEach
循环收集承诺。这就是为什么它们使用Promise.all
。由于您只执行一个操作,因此应该能够返回t.set(docRef,acceptance)
而不使用事务处理[]
。但是,这不应该解决您的问题。在您发布的示例中,事务[]
用于从forEach
循环收集承诺。这就是他们使用承诺的原因。所有。由于您只执行一个操作,您应该能够返回t.set(docRef,acceptance)
没有transArray[]
。但是,这不应该解决您的问题。多谢您的回复,道格。我取出事务数组并返回承诺,看起来是这样的:return db.runTransaction(function(t){const docRef=db.collection('Pending').doc(感谢您的响应,Doug.I取出事务数组并返回承诺,结果如下:返回db.runTransaction(函数(t){const docRef=db.collection('Pending').doc(req.query.inviteId);t.set(docRef,acceptance);})