Reputation: 727
I have a cloud function that uses firebase and after I call it from my angular app I get the mentioned above error:
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
I've searched stack to find solutions - but in most cases there was serialization problem, that I believe DOES NOT happen here.
Here is my function:
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;
});
and the call from Angular app:
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.');
});
Now, the important information is that, the data in firebase realtime database IS CREATED when this function is called and console log does contain "returning ok result" line...
Upvotes: 0
Views: 258
Reputation: 317692
It is still a serialization problem.
Here's what you're trying to send back to the client:
resolve({
status: "Ok",
accessId: accessId,
description: 'Case created'
});
accessId
is the result of a push operation:
var accessId = admin.database().ref('/access/').push();
That means it's a DatabaseReference object, which contains circular references that can't be serialized. It's not a simple data type, like a string.
You'll want to think more carefully about what you want exactly you want to send back to the client app. Maybe you wanted to send back the name or path of the child key that was created by push()
?
Also, you'll probably want to remove the whole new Promise()
thing, as that's an anti-pattern here. There is no need to create a new promise when you have promises from all the other database operations available to work with.
Upvotes: 1