Firebase Admin执行runTransaction事务后新增文档报错问题求助
问题原因
1. 事务逻辑拆分错误,破坏原子性
你将创建子文档的逻辑放在了runTransaction事务外部,会导致两种问题:
- 若计数器更新成功但子文档创建失败,会出现计数器数值虚高、数据不一致的情况
- 全局声明的
counterValue变量在并发请求场景下会被其他请求覆盖,拿到错误的编号值
2. 错误捕获逻辑写反
你在事务回调内部添加了catch,一旦事务执行过程中出错,这个catch会直接吞掉错误,返回状态为已完成的Promise,后续的.then回调仍然会执行,此时counterValue还没有被正确赋值,调用set时自然会抛出空对象相关错误。
3. 异步Promise未正确返回
事务完成后的set操作是异步任务,你没有将它return给外层的Promise链式调用,会导致错误无法被外层捕获,甚至可能出现响应提前返回、异步操作被中断的问题。
修复方案
将子文档创建逻辑移入事务内部,使用事务提供的set方法操作,保证整个流程的原子性,同时删除事务内部的错误捕获,统一交给外层处理:
const db = admin.firestore() // 注意原变量名拼写错误(少了n),这里修正为counterRef const counterRef = db.collection('invoices').doc('invoices_doc') return db.runTransaction((transaction) => { return transaction .get(counterRef) .then((counter) => { // 先判断文档是否存在,避免data()返回undefined if (!counter.exists) { throw new Error('计数器文档不存在') } const counterValue = counter.data().counter + 1 // 更新计数器 transaction.update(counterRef, { counter: counterValue }) // 事务内创建子文档,保证原子性 const newInvoiceRef = counterRef.collection('invoices').doc(String(counterValue)) transaction.set(newInvoiceRef, { series: 'SS', series_nr: counterValue }) // 可选:把编号返回给外部后续使用 return counterValue }) }) .then((counterValue) => { response.status(200).send({ status: 'OK', series_nr: counterValue }) }) .catch((error) => { response.status(200).send({ status: 'OPERATION ERROR', error: error.message }) })
内容的提问来源于stack exchange,提问作者Romanas
相关产品推荐
相关产品推荐

