You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:41:49