Firebase Cloud Functions推送通知报错:注册令牌无效问题排查
问题分析与修复方案
你的代码存在几个关键错误,直接导致了推送token无效的报错,下面逐一说明并给出修复方案:
1. 笔误:afterData 错误引用了 before 的数据
你把更新后的数据来源写成了change?.before?.data(),这会导致beforeData和afterData完全相同,后续的beforeData?.receiverId != afterData?.receiverId判断永远不成立;如果是文档新增场景,beforeData还会是null,彻底打乱逻辑。
修复:
从change.after获取更新后的数据:
const afterData = change?.after?.data();
2. 字符串模板使用错误
你用双引号"包裹了模板字符串,导致变量无法被解析,"users/${afterData?.receiverId}"会被当作字面量路径(即文档路径是users/${afterData?.receiverId},而非实际用户ID对应的路径),最终查询不到目标用户文档,token自然为undefined。
修复:
用反引号`包裹模板字符串,同样要修正推送通知的body字段:
// 用户文档路径 const docRef = admin.firestore().doc(`users/${afterData?.receiverId}`); // 通知内容 body: `${afterData?.senderName} has sent you a message!`,
3. 缺失文档存在性检查与异步操作处理
即使你确认所有用户都有token,也需要先检查文档是否存在,避免因路径错误导致docSnap.data()返回null;同时sendToDevice是异步操作,必须用await等待完成,并添加错误捕获防止函数异常退出。
修复:
在获取用户文档后增加检查逻辑,并用try/catch处理推送操作:
if (!docSnap.exists) { console.log(`用户文档 ${afterData?.receiverId} 不存在`); return; } const userToken = docSnap.data()?.token; if (!userToken) { console.log(`用户 ${afterData?.receiverId} 未设置推送token`); return; } try { await admin.messaging().sendToDevice(userToken, payload); console.log("推送通知发送成功"); } catch (error) { console.error("推送通知发送失败:", error); }
修正后的完整代码
export const messageListener = functions.firestore .document("stingrayMessageListener/stingrayMessageListener") .onWrite(async (change) => { const beforeData = change?.before?.data(); const afterData = change?.after?.data(); // 确保更新后的数据存在 if (!afterData) return; if (beforeData?.receiverId !== afterData?.receiverId) { const docRef = admin.firestore().doc(`users/${afterData.receiverId}`); const docSnap = await docRef.get(); if (!docSnap.exists) { console.log(`用户文档 ${afterData.receiverId} 不存在`); return; } const userToken = docSnap.data()?.token; if (!userToken) { console.log(`用户 ${afterData.receiverId} 未设置推送token`); return; } const payload = { notification: { title: "New message!", body: `${afterData.senderName} has sent you a message!`, }, data: { body: "message", }, }; try { await admin.messaging().sendToDevice(userToken, payload); console.log("推送通知发送成功"); } catch (error) { console.error("推送通知发送失败:", error); } } });
内容的提问来源于stack exchange,提问作者Ruder Buster
相关产品推荐
相关产品推荐

