javascript - Firebase 云函数:“未处理的错误 RangeError:超出最大调用堆栈大小”
问题描述
我有一个使用 firebase 的云功能,从我的 Angular 应用程序调用它后,我收到上述错误:
Unhandled error RangeError: Maximum call stack size exceeded
at baseKeys (/workspace/node_modules/lodash/lodash.js:3483:12)
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
我已经搜索堆栈以找到解决方案 - 但在大多数情况下存在序列化问题,我相信这里不会发生。
这是我的功能:
exports.createCase = functions.region('europe-west2').https.onCall((data, context) => {
console.log("creating new case");
if (!context.auth) {
throw new functions.https.HttpsError('failed-precondition', 'This function must be called ' +
'while authenticated.');
}
const caseName = data.caseName;
// Authentication / user information is automatically added to the request.
const uid = context.auth.uid;
const name = context.auth.token.name || null;
const picture = context.auth.token.picture || null;
const email = context.auth.token.email || null;
console.log("caseName=" + caseName + " uid=" + uid + " name=" + name + " picture=" +
picture + " email=" + email);
var operationResult = new Promise ((resolve, reject) => {
var accessData : any = {};
var accessId = admin.database().ref('/access/').push();
var operationId = admin.database().ref('/operationslog/' + accessId.key + '/').push();
console.log("accessId created=" + accessId + ' || ' + accessId.key + ' operations id=' +
operationId + ' || ' + operationId.key);
let now: number = Date.now();
accessData[`/access/` + accessId.key] = new Access(caseName, uid, email);
accessData[`/operationslog/` + accessId.key + `/` + operationId.key] = {
date: now,
performedByUser: uid,
performedByMail: email,
performedByImg: picture,
performedBySystem: false,
operationType: 'CREATE',
order: (REVERSE_ORDER_MAX - now),
details: {creator: uid, name: caseName}
};
console.log('commiting data');
admin.database().ref().update(accessData).then( (value: void) => {
console.log("returning ok result");
resolve({
status: "Ok",
accessId: accessId,
description: 'Case created'
});
}, err => {
console.log("Error while trying to create case: " + err);
reject("CASE NOT CREATED");
}
).catch(exception => {
console.log("Error while trying to create case: " + exception);
reject("CASE NOT CREATED");
}
);
}
);
return operationResult;
});
以及来自 Angular 应用程序的调用:
let createCaseCall = functions.httpsCallable('createCase');
createCaseCall({caseName: value.caseName}).then(result => {
// Read result of the Cloud Function.
console.log("got result: " + result);
if (result.data.status == 'Ok') {
this.showSuccessMessage('Case created.');
}
}).catch(err => {
console.log("Error while calling cloud functions: " + err);
this.showErrorMessage('Error while creating the case.');
});
现在,重要的信息是,调用此函数时会创建 firebase 实时数据库中的数据,并且控制台日志确实包含“returning ok result”行...
解决方案
它仍然是一个序列化问题。
这是您要发送回客户端的内容:
resolve({
status: "Ok",
accessId: accessId,
description: 'Case created'
});
accessId
是推送操作的结果:
var accessId = admin.database().ref('/access/').push();
这意味着它是一个 DatabaseReference 对象,其中包含无法序列化的循环引用。它不是一个简单的数据类型,如字符串。
您需要更仔细地考虑您想要发送回客户端应用程序的确切内容。也许您想发回由 ? 创建的子密钥的名称或路径push()
?
此外,您可能希望删除整个new Promise()
内容,因为这是一种反模式。当您拥有来自所有其他可用数据库操作的承诺时,无需创建新承诺。
推荐阅读
- android - 使用 Google 的 Paging3 库时显示空状态
- android - 使用同一个 Google Play 控制台帐户分别发布两个具有两个 firebase 帐户的 android 项目会有什么问题吗?
- php - 从 Woocommerce 表格和电子邮件中删除“(含税)”
- vba - Excel 中的 VBA 宏 - 在 ID 为动态时使用 getElementById
- python - 无论我们使用什么程序语言,如何找到句子元素类型?
- reactjs - 在材质 ui 中加载自定义字体 Open Sans 及其变体(粗体、半粗体)
- jquery - Kendo JQuery Grid dataBound 事件未触发
- json - 使用几个变量插值从 bash 管道写入 json
- r - 如何将向量分类到R中的bin中?
- javascript - MQTT.js subscribe() 函数的回调未捕获错误消息