Firebase云函数中JSON.stringify结果与预期不符问题排查
问题排查与解决
问题场景
云函数监听items集合的文档创建事件,将新文档的value1/value2/value3属性存入items/list文档的list字段(存储为JSON字符串格式的数组)。存在以下异常:
- 首次添加文档触发else分支时,
list字段值为'[{"value1":"one","value2":"two","value3":"three"},{}]',不符合预期的'[{"value1":"one","value2":"two","value3":"three"}]' - 当
items/list文档已存在时,触发if分支可正常将新对象追加至数组末尾
使用环境:Firestore云函数模拟器、NodeJS 16
异常原因
else分支中错误使用了update方法:
- Firestore的
update()方法仅能修改已存在的文档,当目标文档(items/list)不存在时,调用update()属于非法操作 - 模拟器环境下未正确抛出该错误,反而生成了包含空对象的异常数组值;生产环境中该操作会直接触发catch分支返回错误
解决方案
将else分支中的update()替换为set()方法,set()支持创建新文档或覆盖已有文档,符合首次添加时创建items/list文档的需求。
修改后的完整handler代码
exports.handler = (snap, context, db) => { try { const data = snap.data() const value1 = data.value1 const value2 = data.value2 const value3 = data.value3 const docRef = db.doc(`items/list`) return docRef .get() .then(docSnap => { if (docSnap.exists) { const list = JSON.parse(docSnap.get('list')) const newList = [...list, { value1: value1, value2: value2, value3: value3, }] return docRef .update({ list: JSON.stringify(newList) }) .then(() => { return { msg: 'success' } }) .catch(error => { return { msg: error } }) } else { const newList = [{ value1: value1, value2: value2, value3: value3, }] // 替换为set方法创建新文档 return docRef .set({ list: JSON.stringify(newList) }) .then(() => { return { msg: 'success' } }) .catch(error => { return { msg: error } }) } }) } catch (error) { return { msg: error } } }
额外优化建议
- 可以直接使用Firestore的数组类型存储列表,无需手动做JSON字符串的解析与序列化,这样能利用Firestore原生的数组操作API(如
arrayUnion)简化代码,同时避免JSON转换的潜在问题 - 建议使用事务处理逻辑,避免并发创建文档或更新数组时出现数据冲突
内容的提问来源于stack exchange,提问作者aabdulahad
相关产品推荐
相关产品推荐

