如何在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
相关产品推荐
相关产品推荐

