事务内部用于获取多个文档的循环无法按预期工作



我试图在一个事务中获取一堆文档,并在同一事务中更新所有文档(因为它们相互引用,所以这必须是原子的(。我知道所有的读取都必须在所有的写入之前进行,但我的控制台中仍然会出现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配置的(

相关内容

  • 没有找到相关文章

最新更新