Firebase Cloud Function:for-of循环读取Firestore数据返回空值问题
问题解决:异步处理导致数据读取空值的修复方案
你的核心问题是异步操作未等待就执行后续代码:db.doc().get()是异步任务,你用then处理但没有等待它完成,后面的categorySelectedBy.map会先执行,这时候categorySelectedBy还是undefined,自然拿不到数据。
下面是修复后的代码,适配Firebase V8非模块化环境:
const functions = require('firebase-functions'); const admin = require('firebase-admin'); admin.initializeApp(); const db = admin.firestore(); // 给回调函数加上async关键字 exports.addProductToUserWhenCreated = functions.firestore.document('products/{documentUid}').onCreate(async (snap, context) => { const productCategories = snap.data().categories; const productId = snap.id; // 遍历每个分类,用await等待异步读取完成 for (const category of productCategories) { // 用await替代then,等待文档读取完成 const categoryDoc = await db.doc(`categories/${category}`).get(); // 先判断文档是否存在,避免空值报错 if (!categoryDoc.exists) { console.log(`分类 ${category} 不存在,跳过`); continue; } const categorySelectedBy = categoryDoc.data().selectedBy; // 确保selectedBy是有效数组再执行写入 if (!Array.isArray(categorySelectedBy) || categorySelectedBy.length === 0) { console.log(`分类 ${category} 没有关注的用户,跳过`); continue; } // 用Promise.all批量处理写入,确保所有操作都完成 const writePromises = categorySelectedBy.map(user => { return db.doc(`users/${user}/selectedProducts/${productId}`).set({ achievedRate: 0, }); }); await Promise.all(writePromises); } return Promise.resolve('所有操作完成'); });
关键改动说明:
- async/await替代then链式调用:把云函数回调改成
async函数,用await等待get()操作完成,确保拿到分类数据后再执行后续逻辑。 - 增加空值判断:避免因分类文档不存在、
selectedBy不是数组等情况导致报错。 - Promise.all批量处理写入:多个用户的写入操作并行执行,同时确保所有写入完成后函数才结束,避免Firebase提前终止函数导致数据丢失。
- 变量声明优化:用
const替代let(不需要重新赋值的变量),提升代码可读性和安全性。
内容的提问来源于stack exchange,提问作者Maxime Crtgn
相关产品推荐
相关产品推荐

