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

如何在TypeScript编写的Google Cloud Function中读取Firebase数据

问题解决与代码修正

首先,你的代码存在几个核心问题:文档访问层级错误、TypeScript类型安全处理缺失、JSON结构语法错误,以及异常抛出逻辑不当。以下是分步修正方案:

1. 修正Firestore文档结构

你提供的JSON存在语法错误,items应该用数组[]包裹(对象{}需要键值对),正确结构如下:

{
  "users": {
    "tim": {
      "score": 1200,
      "health": 200,
      "items": [123123, 182281, 123344]
    },
    "james": {
      "score": 100,
      "health": 50,
      "items": [143553, 567454]
    }
  }
}

2. 修正TypeScript云函数代码

以下是修复后的完整代码,包含类型安全处理和逻辑优化:

import * as admin from "firebase-admin";

// 定义用户数据类型,提供TypeScript类型提示
interface UserData {
  score: number;
  health: number;
  items: number[];
}

export class ScoreHandler {
    constructor(private firestore: FirebaseFirestore.Firestore) {}

    async calculateFinalScore(name: string): Promise<number> {
        try {
            const docSnapshot = await this.firestore
              .collection("users")
              .doc("users")
              .get();
            
            // 先获取文档数据并检查是否存在
            const docData = docSnapshot.data();
            if (!docData) {
                console.warn("无法找到用户文档数据");
                throw new Error("用户文档不存在");
            }

            // 校验users字段和目标用户是否存在
            const users = docData.users as Record<string, UserData>;
            if (!users || !users[name]) {
                console.warn(`无法找到用户${name}的数据`);
                throw new Error(`用户${name}不存在`);
            }

            // 解构获取用户数据
            const { score, health, items } = users[name];
            
            // 计算最终分数,兜底检查items是否为数组
            const finalScore = score * health * (Array.isArray(items) ? items.length : 0);
            return finalScore;
            
        } catch (e) {
            console.error(e);
            return 0.0;
        }
    }
}

关键修正点说明

  • 类型安全处理:通过UserData接口和Record<string, UserData>类型断言,消除TypeScript"对象可能未定义"的警告,同时提供代码提示。
  • 层级访问修正:你的文档数据根节点就是users字段,无需额外嵌套document.data()["users"]之外的层级,直接通过传入的name参数动态获取目标用户数据。
  • 异常逻辑修正:不能直接抛出console.warn,需先打印警告信息再抛出Error对象,确保异常被正确捕获。
  • 兜底检查:增加Array.isArray(items)判断,避免因数据结构异常导致的运行时错误。

更优的Firestore结构建议

如果业务允许,建议将每个用户作为独立文档存储(比如users/tim、users/james),这更符合Firestore的最佳实践,便于查询、更新和权限控制,修正后的代码如下:

async calculateFinalScore(name: string): Promise<number> {
    try {
        const docSnapshot = await this.firestore
          .collection("users")
          .doc(name) // 直接用用户名作为文档ID
          .get();
        
        const userData = docSnapshot.data() as UserData | undefined;
        if (!userData) {
            console.warn(`无法找到用户${name}的文档`);
            throw new Error(`用户${name}不存在`);
        }

        const { score, health, items } = userData;
        return score * health * items.length;
        
    } catch (e) {
        console.error(e);
        return 0.0;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 22:35:10