Firestore云函数读取集合失败:状态变更时无法获取推送令牌
解决Firestore云函数读取集合逻辑未执行的问题
核心问题分析
你的代码中未正确处理Firestore异步操作:db.collection("usersToken").doc(userId).get()是异步方法,返回的是Promise对象而非直接的文档快照。你直接用tokenSnapshot.exists判断,实际是在检查Promise对象的exists属性(该属性不存在,始终为undefined),导致逻辑分支错误,且异步操作未完成时函数可能提前结束,看起来像是读取逻辑未执行。
修复后的完整代码
const {onDocumentUpdated} = require("firebase-functions/v2/firestore"); const {initializeApp} = require("firebase-admin/app"); const {getFirestore} = require("firebase-admin/firestore"); const logger = require("firebase-functions/logger"); const admin = initializeApp(); const db = getFirestore(); // 将回调改为async函数,支持await处理异步操作 exports.sendPushOnStatusActive = onDocumentUpdated("users/{userId}", async (event) => { const afterData = event.data.after.data(); const previousData = event.data.before.data(); // 直接从触发器参数获取userId,比从文档读取更可靠 const userId = event.params.userId; // 空值防护:避免文档数据为空时报错 if (!previousData || !afterData) { logger.log("缺少用户数据:", userId); return null; } if (previousData.status === "review" && afterData.status === "active") { logger.log("用户已激活:", userId); try { // 用await等待异步读取完成,获取真实的文档快照 const tokenSnapshot = await db.collection("usersToken").doc(userId).get(); if (!tokenSnapshot.exists) { logger.log("用户无推送Token:", userId); return null; } const userToken = tokenSnapshot.data().fcmToken; // 新增Token空值检查 if (!userToken) { logger.log("用户Token为空:", userId); return null; } logger.log("激活用户信息:", {userId, token: userToken}); const message = { token: userToken, notification: { title: "Atualização de Status", body: "Parabéns! Seu cadastro foi aprovado e já estamos contando as corridas que você fez.", }, }; // await等待推送发送完成 const response = await admin.messaging().send(message); logger.log("推送通知已发送:", response); return null; } catch (error) { logger.log("处理过程出错:", error); throw new Error("推送通知处理失败"); } } });
关键修改说明
- 异步操作处理:将函数改为
async,用await等待Firestore读取、FCM推送等异步操作完成,确保后续逻辑基于真实结果执行。 - userId获取优化:直接从
event.params.userId获取用户ID,这是触发器路径定义的参数,比从文档数据读取更可靠,避免文档无uid字段的情况。 - 空值防护:新增对文档数据、推送Token的空值检查,避免因数据缺失导致的隐性错误。
- 全局错误捕获:将所有异步逻辑包裹在
try/catch中,能捕获到读取、推送过程中的所有异常,便于排查问题。
额外排查点
- 确认
usersToken集合的文档ID与users集合的文档ID完全一致,避免因ID不匹配导致读取不到数据。 - 查看Firebase控制台的函数日志,确认是否有
用户无推送Token或用户Token为空的日志,判断是Token不存在还是读取失败。 - 验证服务账号的IAM权限是否生效(Cloud Datastore User权限已包含Firestore读取权限,可在IAM控制台确认权限绑定状态)。
内容的提问来源于stack exchange,提问作者Raphael Gatti
相关产品推荐
相关产品推荐

