Javascript Firebase函数-从Google cloud bucket检索文件会导致RangeError:超出最大调用堆栈大小
我正在尝试从存储Firestore备份文件的Google云存储桶中检索Firestore备份文件:Javascript Firebase函数-从Google cloud bucket检索文件会导致RangeError:超出最大调用堆栈大小,javascript,node.js,firebase,google-cloud-functions,google-cloud-storage,Javascript,Node.js,Firebase,Google Cloud Functions,Google Cloud Storage,我正在尝试从存储Firestore备份文件的Google云存储桶中检索Firestore备份文件: export const retrieveFirestoreBackup = functions.https.onCall( async (data: RetrieveFirestoreBackupPayload, context) => { try { return await storage.bucket(bucket).getFiles();
export const retrieveFirestoreBackup = functions.https.onCall(
async (data: RetrieveFirestoreBackupPayload, context) => {
try {
return await storage.bucket(bucket).getFiles();
} catch (error) {
console.log("Error getting backup files.", error);
throw new functionsInit.https.HttpsError("unknown", error);
}
}
);
当我使用Firebase functions emulator时,一切正常。但在部署的Firebase函数中运行相同的代码会导致以下错误:
Unhandled error RangeError: Maximum call stack size exceeded
at isArrayLike (/srv/node_modules/lodash/lodash.js:11333:31)
at keys (/srv/node_modules/lodash/lodash.js:13307:14)
at /srv/node_modules/lodash/lodash.js:4900:21
at baseForOwn (/srv/node_modules/lodash/lodash.js:2990:24)
at Function.mapValues (/srv/node_modules/lodash/lodash.js:13400:7)
at encode (/srv/node_modules/firebase-functions/lib/providers/https.js:179:18)
at /srv/node_modules/lodash/lodash.js:13401:38
at /srv/node_modules/lodash/lodash.js:4905:15
at baseForOwn (/srv/node_modules/lodash/lodash.js:2990:24)
at Function.mapValues (/srv/node_modules/lodash/lodash.js:13400:7)
如何成功地将文件发送到客户端?您的代码正在尝试将
getFiles()
返回的对象序列化为JSON以发送回调用方。API文档说它是一个对象数组
错误消息表明文件对象太复杂,无法使用默认JSON序列化发送。从API文档中可以看出,它们都包含一个Bucket对象,而Bucket对象本身可能包含许多其他实现细节。如果您想了解单个文件对象的复杂性,请仔细查看其内部细节。也许所有这些都适合您机器上的内存,但不适合云功能服务器实例提供的有限内存
您可能应该做的是从getFiles迭代文件对象数组,并构建一个新数组,其中只包含要发送回客户机的文件的数据。如果您只需要文件的路径,那么就可以将响应减少到一个简单的字符串数组,这对于文件数量有限的bucket应该是可以的。请记住,云函数响应的最大大小只能是10MB,因此对于非常大的存储桶,您可能会遇到问题。请根据Doug Stevenson的建议发布我的修订代码,供需要的人使用:
export const retrieveFirestoreBackup = functions.https.onCall(
async (data: RetrieveFirestoreBackupPayload, context) => {
try {
const [files] = await storage.bucket(bucket).getFiles();
const metadataArray = await Promise.all(
files.map(file => {
return file.getMetadata().then(result => result[0]);
})
);
return metadataArray;
} catch (error) {
console.log("Error getting backup files.", error);
throw new functionsInit.https.HttpsError("unknown", error);
}
}
);