Firebase Google Cloud Function返回Snapshot报错问题咨询
是否可以从Firebase Google Cloud Function中直接返回Snapshot对象?
你当前编写的可调用云函数代码如下:
exports.getFreshData = functions.https.onCall(async (data, context) => { const ref = data.ref; try { const snap = await admin.database().ref(ref).once("value"); return {res: true, snapshot: snap}; } catch (e) { error(e); return false; } });
客户端调用该函数时抛出如下栈溢出错误:
Unhandled error RangeError: Maximum call stack size exceeded at keys (/workspace/node_modules/lodash/lodash.js:13333:60) at /workspace/node_modules/lodash/lodash.js:4920:21 at baseForOwn (/workspace/node_modules/lodash/lodash.js:2990:24) at Function.mapValues (/workspace/node_modules/lodash/lodash.js:13426:7) at encode (/workspace/node_modules/firebase-functions/lib/providers/https.js:184:18) at /workspace/node_modules/lodash/lodash.js:13427:38 at /workspace/node_modules/lodash/lodash.js:4925:15 at baseForOwn (/workspace/node_modules/lodash/lodash.js:2990:24) at Function.mapValues (/workspace/node_modules/lodash/lodash.js:13426:7) at encode (/workspace/node_modules/firebase-functions/lib/providers/https.js:184:18)
将返回值替换为snap.val()后函数可正常运行,需要确认直接返回Snapshot对象的需求是否可实现。
结论
无法直接返回原生的DataSnapshot对象。
原因
- Firebase可调用云函数会对返回值自动执行JSON序列化操作,而Admin SDK返回的
DataSnapshot是类实例,内部包含大量循环引用的属性、内置方法,序列化过程中递归遍历属性会触发无限递归,最终导致栈溢出,和你遇到的报错完全吻合。 - 跨网络传输仅支持纯可序列化的JSON数据,即使通过特殊手段绕过序列化校验,客户端接收到的也只是普通JSON对象,不会附带
val()、exists()、child()等Snapshot原型上的方法,完全不具备原生Snapshot的使用价值。
可行替代方案
如果需要使用Snapshot除存储值之外的其他属性,手动提取需要的字段组装为纯JSON对象返回即可,示例代码如下:
exports.getFreshData = functions.https.onCall(async (data, context) => { const ref = data.ref; // 务必在此处添加ref路径合法性校验,避免越权访问 try { const snap = await admin.database().ref(ref).once("value"); return { res: true, snapshot: { val: snap.val(), key: snap.key, exists: snap.exists(), // 可按需追加你需要的其他Snapshot属性 } }; } catch (e) { functions.logger.error(e); return {res: false, msg: e.message}; } });
内容的提问来源于stack exchange,提问作者aritroper
相关产品推荐
相关产品推荐

