在Firebase异步函数中调用另一个异步函数时遇TypeError错误求助
问题排查:调用getViews时触发TypeError错误
错误信息
TypeError: Cannot read properties of undefined (reading 'on')
场景说明
通过getViews、getViewCount和updateCount三个异步函数实现「获取YouTube播放量并存储到Firestore数据库」的功能,但在updateCount内调用getViews时触发上述错误。
相关代码
getViews函数
exports.getViews = functions .runWith({ secrets: ["YOUTUBE_API"] }) .https.onCall(async (data, context) => { const count = await getViewCount({}); return count; });
updateCount函数
exports.updateCount = functions.https.onRequest(async (req, res) => { const viewData = await this.getViews({ "h": "j" }); // 错误触发位置 const addData = await admin .firestore() .collection("viewCount") .doc("Count") .set(viewData) .then(() => { console.log("Document successfully written!"); }) .catch((error) => { console.error("Error writing document: ", error); }); });
getViewCount函数
const getViewCount = async (arg) => { const youtube = google.youtube({ version: "v3", auth: process.env.YOUTUBE_API, }); const count = await youtube.channels.list({ id: process.env.YOUTUBE_CHANNEL_ID, part: "statistics", }); const countData = count.data.items[0].statistics.viewCount; return countData; }
问题原因及修复方案
核心问题
updateCount中使用this.getViews是错误的调用方式:getViews是导出的Cloud Function,并非类的成员方法,在onRequest的执行上下文里this指向undefined,导致this.getViews返回undefined,进而触发读取on属性的错误。
修复方案(二选一即可)
方案1:直接调用getViewCount(推荐)
既然getViews内部本质是调用getViewCount,在updateCount里可以直接复用getViewCount函数,跳过HTTP Callable函数的封装,更高效且避免跨函数调用的问题:
exports.updateCount = functions.https.onRequest(async (req, res) => { try { const viewData = await getViewCount({}); // 建议将播放量包装为对象存储,避免Firestore存储纯值的潜在问题 await admin.firestore().collection("viewCount").doc("Count").set({ viewCount: viewData }); console.log("Document successfully written!"); res.status(200).send("更新成功"); } catch (error) { console.error("更新失败: ", error); res.status(500).send("更新失败"); } });
方案2:通过HTTP请求调用getViews(若需复用getViews的权限校验等逻辑)
如果必须调用getViews这个Callable函数,需要通过标准HTTP请求触发,而非直接当作普通函数调用:
const fetch = require('node-fetch'); // 需先安装node-fetch依赖 exports.updateCount = functions.https.onRequest(async (req, res) => { try { const response = await fetch(`https://${process.env.GCLOUD_PROJECT}.cloudfunctions.net/getViews`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ data: { "h": "j" } }) // Callable函数要求请求体包含data字段 }); const result = await response.json(); if (result.error) throw new Error(result.error.message); const viewData = result.data; await admin.firestore().collection("viewCount").doc("Count").set({ viewCount: viewData }); console.log("Document successfully written!"); res.status(200).send("更新成功"); } catch (error) { console.error("更新失败: ", error); res.status(500).send("更新失败"); } });
内容的提问来源于stack exchange,提问作者bagel_boy3
相关产品推荐
相关产品推荐

