如何解决事务内部循环以获取多个文档无法按预期工作
我试图在一个事务中获取一堆文档,并在同一个事务中更新所有文档(因为它们彼此引用,所以必须是原子的)。我知道所有读取都必须在所有写入之前进行,但是在控制台中仍然出现The referenced transaction has expired or is no longer valid
错误。
我看到console.log(Transaction id: ${transactionId})
打印的所有ID,但没有console.log(Transaction ${transactionId} fetched and pushed to array)
的单个输出。
我的交易出了什么问题?
try {
return admin.firestore().runTransaction(async t => {
const bundleRef = admin.firestore().doc(`bundles/${bundleId}`)
const bundle = await t.get(bundleRef)
const bundleData = bundle.data()
const transactions:FirebaseFirestore.DocumentSnapshot[] = []
await bundleData!.transactionIds.forEach(async (transactionId: string) => {
console.log(`Transaction id: ${transactionId}`)
const transactionRef = admin.firestore().doc(`transactions/${transactionId}`)
const transaction = await t.get(transactionRef)
transactions.push(transaction)
console.log(`Transaction ${transactionId} fetched and pushed to array`)
})
console.log(`All transactions fetched`)
transactions.forEach(async transaction => {
console.log(`Updating transaction ${transaction.id}`)
const transactionData = transaction.data()
transactionData!.timestamp = admin.firestore.FieldValue.serverTimestamp()
t.update(transaction.ref,transactionData!)
console.log(`Transaction ${transaction.id} updated`)
})
console.log(`Update bundle ${bundle.id}`)
bundleData!.timestamp = admin.firestore.FieldValue.serverTimestamp()
t.update(bundle.ref,bundleData!)
console.log(`Finished`)
})
} catch (err) {
return Promise.reject(new Error("Transaction failed."));
}
解决方法
如Doug在其评论中所解释的,您不能以这种方式使用forEach()
和async/await
。要获取所有交易凭证,最好的方法是使用getAll()
方法,如下所示:
try {
return admin.firestore().runTransaction(async t => {
const bundleRef = admin.firestore().doc(`bundles/${bundleId}`)
const bundle = await t.get(bundleRef)
const bundleData = bundle.data()
const transactionRefs = []
bundleData.transactionIds.forEach((transactionId) => {
const transactionRef = admin.firestore().doc(`transactions/${transactionId}`)
transactionRefs.push(transactionRef);
})
const transactionSnapshots = await t.getAll(...transactionRefs);
transactionSnapshots.forEach(transactionSnap => {
t = t.update(transactionSnap.ref,{ timestamp: admin.firestore.FieldValue.serverTimestamp() });
})
t.update(bundle.ref,{ timestamp: admin.firestore.FieldValue.serverTimestamp() })
console.log(`Finished`)
})
} catch (err) {
console.log(err)
return null;
}
请注意:
- 您不需要执行
transactionData!.timestamp = admin.firestore.FieldValue.serverTimestamp()
,因为您实际上是在使用相同的值覆盖现有文档数据!只需更新时间戳,因为它是唯一更改的字段(如果我正确理解的话) - (我删除了所有对象类型,因为目前我正在使用的计算机中唯一的项目已针对JavaScript配置)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。