我正在调用Firebase可调用函数,并返回Firebase指定的Promise,但出现此错误:
未处理的错误RangeError:超出最大调用堆栈大小
代码如下:
exports.getProductInfo = functions.https.onCall((data, context) => {
// Message text passed from the client.
const product = data.product;
// Authentication / user information is automatically added to the request.
// const uid = context.auth.uid;
// Get the current Server Timestamp
var ts = String(Date.now());
var key, snap, node;
// Get the price of the specified product
return database.ref('/products/' + product)
.orderByKey()
.endAt(ts)
.limitToLast(1)
.once('value', function (snapshot) {
snap = snapshot.val();
console.log('snap: ' + JSON.stringify(snap));
key = Object.keys(snap)[0];
node = snap[key];
console.log('node: ' + JSON.stringify(node));
return(node);
});
});
这是我在功能日志中看到的输出:
快照:{“ 1538004276”:{“ description”:“这是基本产品”,“ price”:40}}
节点:{“ description”:“这是基本产品”,“ price”:40}
Unhandled error RangeError: Maximum call stack size exceeded
at Object (native)
at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:4905:24
at baseForOwn (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:2996:24)
at Function.mapValues (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13401:7)
at encode (/user_code/node_modules/firebase-functions/lib/providers/https.js:242:18)
at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13402:38
at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:4911:15
at baseForOwn (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:2996:24)
at Function.mapValues (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13401:7)
at encode (/user_code/node_modules/firebase-functions/lib/providers/https.js:242:18)
at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13402:38
at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:4911:15
at baseForOwn (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:2996:24)
at Function.mapValues (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13401:7)
at encode (/user_code/node_modules/firebase-functions/lib/providers/https.js:242:18)
at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13402:38
at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:4911:15
at baseForOwn (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:2996:24)
at Function.mapValues (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13401:7)
at encode (/user_code/node_modules/firebase-functions/lib/providers/https.js:242:18)
at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13402:38
at /user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:4911:15
at baseForOwn (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:2996:24)
at Function.mapValues (/user_code/node_modules/firebase-functions/node_modules/lodash/lodash.js:13401:7)
帮助!
答案 0 :(得分:2)
问题类似于the one described here。您将返回由Firebase API生成的称为DocumentSnapshot的复杂对象。快照本身不是返回给客户端的原始JSON数据,它包含对其他对象的循环引用。 Cloud Functions卡在试图序列化所有这些对象的过程中。相反,只需在快照上调用val()
即可在感兴趣的位置返回数据的原始JavaScript对象:
return database
.ref('/products/' + product)
.orderByKey()
.endAt(ts)
.limitToLast(1)
.once('value') // once() returns a promise containing a snapshost
.then(snapshot => {
return snapshot.val() // this is the raw JS object
})
您通常不会在同一调用中同时使用返回的诺言和回调。只使用诺言就更容易了。
答案 1 :(得分:1)
对我来说,解决方案是将收益包装在Promise中:
exports.getIssue = functions.https.onCall(data => {
const issueKey = data.issueKey
return new Promise((resolve, reject) => {
admin
.database()
.ref('issue')
.child(issueKey)
.once('value', snapIssue => {
let issue = snapIssue.val()
if (issue) {
return resolve(issue)
} else {
reject('Issue not found')
}
})
.catch(reject)
})
答案 2 :(得分:1)
值得一提的是,这并未明确地写在Firebase doc中;您应该始终在HTTP请求之前对对象进行字符串化。另一方面,只需对其进行解析。删除JSON.stringify()和JSON.parse()将触发完全相同的错误。
客户端:
auth.signInWithEmailAndPassword(username, password).then(async (snapShot) => {
const getToken = await functions.httpsCallable('getToken')(JSON.stringify(snapShot));
....
});
服务器端:
exports.getToken = functions.https.onCall(async (data, context) => {
console.log(JSON.parse(data));
...
});