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

Firebase Functions本地调试报错:Cannot read properties of undefined (reading 'toString')

Firebase Functions模拟器调用报错:Cannot read properties of undefined (reading 'toString')

问题描述

我正在调试用于触发通知的Firebase Functions,通过Firebase CLI执行firebase emulators:start命令启动模拟器。但调用localhost:5001上的函数时,出现错误Cannot read properties of undefined (reading 'toString'),终端也输出对应的TypeError堆栈信息。

调用的本地URL为:http://localhost:5001/projectname-83750/us-central1/sendNotificationOnFighterDataChangeToFans-0

函数代码如下:

const functions = require("firebase-functions");
const admin = require("firebase-admin");

admin.initializeApp({
  credential: admin.credential.applicationDefault(),
  databaseURL: "https://console.firebase.google.com/project/projectname",
});

exports.sendNotificationOnFighterDataChangeToFans = functions.firestore
    .document("users/{userId}")
    .onUpdate(async (change, context) => {
      const before = change.before.data(); // Data before the change
      const after = change.after.data(); // Data after the change

      // Check if userName changed
      if (before.weightClass !== after.weightClass) {
        const userId = context.params.userId;

        const fighterSnapshot = await admin
            .firestore()
            .collection("users")
            .doc(userId)
            .get();

        const fighterData = fighterSnapshot.data();

        if (fighterData && fighterData.route === "fighter") {
          const followers = fighterData.followers || [];

          const fanPromises = followers.map(async (followerId) => {
            const fanSnapshot = await admin
                .firestore()
                .collection("users")
                .doc(followerId)
                .get();

            const fanData = fanSnapshot.data();
            if (fanData && fanData.route === "fan" && fanData.deviceToken) {
              const notification = {
                token: fanData.deviceToken,
                notification: {
                  title: "UserName Changed",
                  body: `Your userName has been changed to ${after.userName}`,
                },
              };

              try {
                await admin.messaging().send(notification);
                console.log("Notification sent successfully");
              } catch (error) {
                console.error("Error sending notification:", error);
              }
            }
          });

          await Promise.all(fanPromises);
        }
      }
    });

问题分析与修复步骤

1. DatabaseURL配置错误

admin.initializeApp中的databaseURL填写错误,应该使用Firebase Realtime Database的官方URL(格式为https://<project-id>.firebaseio.com),而非控制台页面链接。错误的URL会导致Admin SDK初始化异常,进而触发toString相关的TypeError。

修复代码:

admin.initializeApp({
  credential: admin.credential.applicationDefault(),
  databaseURL: "https://projectname-83750.firebaseio.com", // 替换为你的项目实际Realtime Database地址
});

2. 错误的函数调用方式

你通过HTTP URL直接调用了Firestore的onUpdate触发器函数,这不符合触发器的运行逻辑。Firestore触发器函数只能由对应文档的更新事件触发,无法通过HTTP请求直接调用。

正确测试方式:

  • 在Firestore模拟器中修改users集合下任意文档的weightClass字段,自动触发函数执行;
  • 若需通过HTTP测试通知逻辑,可单独编写HTTP触发器函数,或使用Firebase Emulator Suite的UI模拟Firestore事件。

3. 冗余的文档读取操作

onUpdate触发器已通过change.before和change.after提供了文档的前后数据,无需再次读取users/{userId}文档,这会增加不必要的资源开销。可以直接使用after.data()获取最新数据:

优化代码片段:

// 替换原有的fighterSnapshot和fighterData读取逻辑
const fighterData = after.data();
if (fighterData && fighterData.route === "fighter") {
  // 后续逻辑保持不变
}

4. 通知内容与判断逻辑不匹配

判断条件是检查weightClass是否变化,但通知标题和内容却标注为"UserName Changed",逻辑与内容不一致,需修正:

notification: {
  title: "Weight Class Updated",
  body: `The weight class of your followed fighter has changed to ${after.weightClass}`,
},

内容的提问来源于stack exchange,提问作者EnCoder2000

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 04:10:26