如何在多操作场景下正确返回Firestore事务的Promise?
解决Firestore事务的「Error: Transaction callback must return a Promise」问题及相关疑问
一、错误原因与解决方法
这个错误的核心原因是Firestore事务的回调函数必须返回一个Promise,以此告知事务所有操作已完成。如果回调内的异步操作没有正确返回Promise,就会触发该报错。
最直观的解决方式是用async/await编写回调逻辑——async函数本身会返回Promise,完全符合Firestore的要求。示例代码如下:
async function handleSubmit() { try { await db.runTransaction(async (transaction) => { // 1. 读取并更新当前登录用户的联系人数据 const userContactRef = db.collection('users').doc(currentUserId).collection('contacts').doc(targetUserId); const userContactDoc = await transaction.get(userContactRef); const updatedUserContact = { ...userContactDoc.data(), lastMessage: newMessageContent, lastMessageTime: new Date() }; transaction.set(userContactRef, updatedUserContact); // 2. 读取并更新待联系用户的未读消息数 const targetContactRef = db.collection('users').doc(targetUserId).collection('contacts').doc(currentUserId); const targetContactDoc = await transaction.get(targetContactRef); const newUnreadCount = (targetContactDoc.data()?.unreadCount || 0) + 1; transaction.update(targetContactRef, { unreadCount: newUnreadCount }); // 3. 写入新消息数据 const messageRef = db.collection('messages').doc(); transaction.set(messageRef, { senderId: currentUserId, receiverId: targetUserId, content: newMessageContent, timestamp: new Date() }); }); console.log('事务执行成功'); } catch (error) { console.error('事务失败:', error); } }
如果不习惯用async/await,也可以通过.then()串联所有操作形成Promise链返回,但async/await的可读性更强,更易维护。
二、能否将所有逻辑整合到单个transaction.get中?
不行。transaction.get()是针对单个文档引用的方法,每次调用只能获取一个文档的快照。你的操作涉及至少三个不同的文档(当前用户的联系人文档、目标用户的联系人文档、新消息文档),必须分别调用transaction.get()来读取对应文档,才能在事务中安全地进行后续修改。
不过所有逻辑可以放在同一个事务回调函数内完成,就像上面的示例一样——在一个async回调里依次执行多个get、update、set操作,只要确保所有异步操作都被await,回调函数就会自动返回符合要求的Promise。
内容的提问来源于stack exchange,提问作者Abby
相关产品推荐
相关产品推荐

