Firestore事务:是否需要等待所有事务操作完成?
await t.update()的作用及省略await的影响 问题描述
我在Firestore官方文档中看到这段事务代码:
const cityRef = db.collection('cities').doc('SF'); try { const res = await db.runTransaction(async t => { const doc = await t.get(cityRef); const newPopulation = doc.data().population + 1; if (newPopulation <= 1000000) { await t.update(cityRef, { population: newPopulation }); return `Population increased to ${newPopulation}`; } else { throw 'Sorry! Population is too big.'; } }); console.log('Transaction success', res); } catch (e) { console.log('Transaction failure:', e); }
但我搞不懂第8行的await t.update()有什么作用,想知道如果去掉这个await,程序还能正常运行吗?
回答
嘿,这个问题问到点子上了,咱们把这事掰扯明白:
首先得明确,t.update()是Firestore事务对象提供的异步方法,它返回一个Promise——也就是说,它不会立刻完成数据更新,而是要和Firestore服务器完成通信后才会标记操作完成。
为什么必须加await?
事务原子性的核心要求:Firestore事务的本质是保证所有操作「要么全成,要么全败」。如果你不等待
t.update()完成,事务的异步回调函数可能会在更新操作还没得到服务器确认时就提前结束。这时候Firestore无法确认你的更新是否生效,很大概率会直接放弃这个更新,结果就是你以为事务成功了,但数据库里的population数值根本没变化。错误处理不能漏:如果
t.update()执行中出了问题(比如权限不够、文档被其他事务锁定),不加await的话,这个错误会直接变成未捕获的Promise异常,既不会被外层的try/catch捕获,你也完全不知道更新失败了,排查起来会特别头疼。逻辑顺序的严谨性:哪怕这个例子里更新后没有后续操作,但如果你的事务逻辑更复杂(比如要基于这次更新的结果再做其他修改),不等待更新完成就执行下一步,拿到的还是旧数据,直接导致逻辑出错。
去掉await会发生什么?
- 最常见的情况:事务回调提前结束,Firestore不会等待未完成的
update操作,最终数据更新不会被提交,但你的代码会走到成功日志那一步,产生「操作成功」的错觉。 - 极端情况:如果
t.update()的Promise在事务结束后才抛出错误,这个未捕获的异常可能会导致应用崩溃,或者留下难以追踪的隐性bug。
总结一下:在Firestore事务里,所有事务对象的异步方法(t.get()、t.update()、t.set()等)都必须用await等待完成,这是保证事务正确执行的硬性要求,绝对不能省。
内容的提问来源于stack exchange,提问作者Raul

