Node.js ReferenceError问题排查及设备组通知代码正确性咨询
问题分析与修复方案
首先看你遇到的ReferenceError: options is not defined,这个错误原因很直接——你在代码最外层直接调用了request(options, ...),但这时候options变量还没被定义!这段外层的request调用完全是多余的,删掉它就能解决这个报错。
接下来我们一步步梳理你代码里的其他问题,以及对应的修复方式:
1. 多余的全局request调用
你在导入模块后直接写了这段代码:
request(options, function (error, response, body) { console.log(body) })
此时options还未声明,这就是触发错误的根源,直接删除这段代码即可。
2. 异步流程处理错误
你调用request创建设备组后,直接尝试用var notificationKey = body;获取结果,但request是异步操作,这时候body还没有返回值,会导致notificationKey为undefined,后续的sendToDeviceGroup调用必然失败。
我们可以改用支持Promise的request-promise库,配合async/await来简化异步流程,确保拿到设备组密钥后再发送通知。
3. FCM设备组API的细节问题
- 你使用的
https://android.googleapis.com/gcm/notification是旧版GCM的端点,现在应该使用FCM的官方端点:https://fcm.googleapis.com/fcm/notification - 请求头里的
Authorization格式要注意,key和密钥之间不要有空格,正确格式是key=YOUR_SERVER_KEY notification_key_name应该是用户的唯一标识(比如用户邮箱、UID),而不是固定的you@example.com,这样才能为每个用户创建独立的设备组
修复后的完整代码
下面是调整后的代码,解决了所有问题,同时用async/await让异步逻辑更清晰:
'use strict'; const functions = require('firebase-functions'); const admin = require('firebase-admin'); const request = require('request-promise'); // 改用request-promise支持Promise,适配async/await admin.initializeApp(); // 配置请求头,替换成你的FCM服务器密钥 const headers = { 'Authorization': 'key=YOUR_FCM_SERVER_KEY', 'Content-Type': 'application/json' }; exports.sendNotification = functions.firestore.document("Users/{user_id}/Notifications/{notification_id}") .onWrite(async (change, context) => { // 改为async函数 const user_id = context.params.user_id; const notification_id = context.params.notification_id; // 获取当前通知的文档数据 const notificationDoc = await admin.firestore() .collection("Users").doc(user_id) .collection("Notifications").doc(notification_id) .get(); const from_user_id = notificationDoc.data().from; const from_message = notificationDoc.data().message; // 并行获取发送方和接收方的用户信息 const [fromUserDoc, toUserDoc] = await Promise.all([ admin.firestore().collection("Users").doc(from_user_id).get(), admin.firestore().collection("Users").doc(user_id).get() ]); const from_name = fromUserDoc.data().name; const token_id = toUserDoc.data().token_id; const userUniqueId = toUserDoc.data().email || user_id; // 用用户邮箱或UID作为设备组唯一标识 // 创建设备组并获取notification_key const deviceGroupRes = await request({ url: 'https://fcm.googleapis.com/fcm/notification', method: 'POST', headers: headers, json: { 'operation': 'create', 'notification_key_name': userUniqueId, 'registration_ids': [token_id] } }); const notificationKey = deviceGroupRes.notification_key; // 构造通知内容 const payload = { notification: { title: `Notification From: ${from_name}`, body: from_message, icon: "notification.png", sound: "orion.mp3" } }; // 发送设备组通知 const sendResult = await admin.messaging().sendToDeviceGroup(notificationKey, payload); console.log("Notification sent successfully", sendResult); return sendResult; });
额外建议
- 可以把用户的
notification_key存储到Firestore的用户文档中,下次发送时直接读取,避免重复创建设备组 - 添加
try/catch块捕获异步操作中的异常,防止云函数因未处理的错误崩溃 - 确保你的FCM服务器密钥正确,可在Firebase控制台「项目设置」->「云消息传递」中获取
内容的提问来源于stack exchange,提问作者rituparna
相关产品推荐
相关产品推荐

