You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 22:09:03