typescript - 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) 是我要返回的承诺。不?
解决方案
请阅读文档Transaction set()
- 它不会返回承诺。这可能会使 Firestore SDK 感到困惑,因为您返回Promise.all()
的不是承诺的东西。所以也许它认为你返回了一个错误。
您可能根本不需要从事务处理函数返回任何内容。只需打电话就set()
可以了。如果你想通过它返回的承诺将该值传递给 runTransaction 的调用者,你只需要从你的事务处理程序返回一些东西。
顺便说一句,在您的第一个示例中,您不应该将承诺收集到在处理程序函数之外定义的数组中。如果事务处理程序运行不止一次,这可能会导致问题。正如我链接到的文档所说:
不要在事务函数中修改应用程序状态。这样做会引入并发问题,因为事务函数可以多次运行,并且不能保证在 UI 线程上运行。
该事务之外的数组将被视为“应用程序状态”,因为它不在函数本身内部。
推荐阅读
- php - 测试 facebook business-sdk 时出错
- open-telemetry - 从隐式上下文中获取当前活动范围
- python - 使用 Django 在多边形中实现点搜索
- javascript - 错误太多重新渲染。react 限制渲染次数以防止无限循环
- python - 错误:需要 Microsoft Visual C++ 14.0 或更高版本
- python - 在 python modulenotfounderror 中:没有名为“json”的模块
- python - Python np.fromfile 给出错误:Errno 2 No such file or directory
- android - 移动视频转码的最佳参数。请指教
- python - 如果不在值范围内,Python Pandas 会替换值
- python - Python 写入 GRIB 文件