Firebase Cloud Function - RangeError: Maximum call stack size exceeded
Firebase Cloud Function - RangeError: Maximum call stack size exceeded
我正在尝试写一个 onCall
Firebase Cloud Function that calls an external Zoho Desk API 到 return 支持票列表。
但每当我调用我的 Firebase 云函数时,它 return 都会出现此错误:Unhandled error RangeError: Maximum call stack size exceeded
。
我找到的大多数其他答案都与 Firebase 文档快照有关,他们说这是由无限循环引起的。但我不确定如何将这些知识应用到我的外部 api 调用中。
这里是有问题的云函数:
export const getZohoDeskTickets = functions
.region('us-central1')
.https.onCall(async (data, context) => {
// Check if it passed App Check
if (context.app == undefined) {
throw new functions.https.HttpsError(
'failed-precondition',
'The function must be called from an App Check verified app.'
);
}
// Check the authentication
if (!context.auth) {
// Throwing an HttpsError so that the client gets the error details.
throw new functions.https.HttpsError(
'unauthenticated',
'The function must be called while authenticated.'
);
}
// Do the operation
const zohoAccessToken = await getSecretVersion(
'zoho-self-client-api-access-token'
).catch((error) => {
throw new functions.https.HttpsError('unknown', error.message, error);
});
return axios
.get('https://desk.zoho.com/api/v1/tickets', {
headers: {
orgId: '123456789',
Authorization: `Zoho-oauthtoken ${zohoAccessToken}`,
},
})
.catch(async (error) => {
functions.logger.error(error.response.data);
throw new functions.https.HttpsError(
'unknown',
error.response.data.message,
error.response.data
);
});
});
更新:
我发现 this helpful thread 这表明有时无限循环不是来自 Cloud Function 而来自调用者,而且调用堆栈可以帮助调试。
出于兴趣,这是我的调用堆栈,如 Firebase 模拟器日志中所示。这对我来说没有意义,因为它只是一次又一次重复的同一行:
Unhandled error RangeError: Maximum call stack size exceeded
at TCP.get [as reading] (_tls_wrap.js:617:7)
at Function.entries (<anonymous>)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:157:37)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
这里是 Chrome 浏览器控制台调用堆栈:
postJSON @ index.esm2017.js?6f1f:499
call @ index.esm2017.js?6f1f:553
await in call (async)
eval @ index.esm2017.js?6f1f:485
eval @ SupportPage.vue?c3cc:37
eval @ index.js??clonedRule…tup=true&lang=ts:15
__awaiter @ index.js??clonedRule…tup=true&lang=ts:11
handleClick @ SupportPage.vue?c3cc:36
callWithErrorHandling @ runtime-core.esm-bundler.js?f781:155
callWithAsyncErrorHandling @ runtime-core.esm-bundler.js?f781:164
emit @ runtime-core.esm-bundler.js?f781:718
eval @ runtime-core.esm-bundler.js?f781:7232
onClick @ QBtn.js?9c40:148
callWithErrorHandling @ runtime-core.esm-bundler.js?f781:155
callWithAsyncErrorHandling @ runtime-core.esm-bundler.js?f781:164
invoker @ runtime-dom.esm-bundler.js?9cec:366
这是我的 Vue 应用程序中的调用函数:
<template>
<v-btn design="alpha" @click="handleClick">loadData</v-btn>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import VBtn from 'src/components/VBtn.vue';
import { httpsCallable, FunctionsError } from 'firebase/functions';
import { functions } from 'src/config/firebase';
const data = ref();
const getZohoDeskTickets = httpsCallable(functions, 'getZohoDeskTickets');
const isFunctionsError = (error: unknown): error is FunctionsError => {
return (error as FunctionsError).details !== undefined;
};
const handleClick = async () => {
const ticket = await getZohoDeskTickets().catch((error) => {
if (isFunctionsError(error)) {
console.log(error.code);
console.log(error.message);
console.log(error.details);
} else {
console.log(error);
}
});
data.value = ticket;
console.log(ticket);
return ticket;
};
</script>
但即便如此我还是想不通。
无限循环的原因是什么?
或者可能是其他原因导致了这个错误?
终于明白了!
解决方案来自。
简而言之;我需要像这样在返回的 axios 链上添加一个 .then()
:
export const getZohoDeskTickets = functions
.region('us-central1')
.https.onCall(async (data, context) => {
// Check if it passed App Check
if (context.app == undefined) {
throw new functions.https.HttpsError(
'failed-precondition',
'The function must be called from an App Check verified app.'
);
}
// Check the authentication
if (!context.auth) {
// Throwing an HttpsError so that the client gets the error details.
throw new functions.https.HttpsError(
'unauthenticated',
'The function must be called while authenticated.'
);
}
// Do the operation
const zohoAccessToken = await getSecretVersion(
'zoho-self-client-api-access-token'
).catch((error) => {
throw new functions.https.HttpsError('unknown', error.message, error);
});
return axios
.get('https://desk.zoho.com/api/v1/tickets', {
headers: {
orgId: '774638961',
Authorization: `Zoho-oauthtoken ${zohoAccessToken}`,
},
})
.then((response) => {
functions.logger.info(response.data);
return response.data;
})
.catch((error) => {
functions.logger.error(error.response.data);
throw new functions.https.HttpsError(
'unknown',
error.response.data.message,
error.response.data
);
});
});
我正在尝试写一个 onCall
Firebase Cloud Function that calls an external Zoho Desk API 到 return 支持票列表。
但每当我调用我的 Firebase 云函数时,它 return 都会出现此错误:Unhandled error RangeError: Maximum call stack size exceeded
。
我找到的大多数其他答案都与 Firebase 文档快照有关,他们说这是由无限循环引起的。但我不确定如何将这些知识应用到我的外部 api 调用中。
这里是有问题的云函数:
export const getZohoDeskTickets = functions
.region('us-central1')
.https.onCall(async (data, context) => {
// Check if it passed App Check
if (context.app == undefined) {
throw new functions.https.HttpsError(
'failed-precondition',
'The function must be called from an App Check verified app.'
);
}
// Check the authentication
if (!context.auth) {
// Throwing an HttpsError so that the client gets the error details.
throw new functions.https.HttpsError(
'unauthenticated',
'The function must be called while authenticated.'
);
}
// Do the operation
const zohoAccessToken = await getSecretVersion(
'zoho-self-client-api-access-token'
).catch((error) => {
throw new functions.https.HttpsError('unknown', error.message, error);
});
return axios
.get('https://desk.zoho.com/api/v1/tickets', {
headers: {
orgId: '123456789',
Authorization: `Zoho-oauthtoken ${zohoAccessToken}`,
},
})
.catch(async (error) => {
functions.logger.error(error.response.data);
throw new functions.https.HttpsError(
'unknown',
error.response.data.message,
error.response.data
);
});
});
更新:
我发现 this helpful thread 这表明有时无限循环不是来自 Cloud Function 而来自调用者,而且调用堆栈可以帮助调试。
出于兴趣,这是我的调用堆栈,如 Firebase 模拟器日志中所示。这对我来说没有意义,因为它只是一次又一次重复的同一行:
Unhandled error RangeError: Maximum call stack size exceeded
at TCP.get [as reading] (_tls_wrap.js:617:7)
at Function.entries (<anonymous>)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:157:37)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
at encode (/Users/macbook/Dev/my-app/functions/node_modules/firebase-functions/lib/common/providers/https.js:158:22)
这里是 Chrome 浏览器控制台调用堆栈:
postJSON @ index.esm2017.js?6f1f:499
call @ index.esm2017.js?6f1f:553
await in call (async)
eval @ index.esm2017.js?6f1f:485
eval @ SupportPage.vue?c3cc:37
eval @ index.js??clonedRule…tup=true&lang=ts:15
__awaiter @ index.js??clonedRule…tup=true&lang=ts:11
handleClick @ SupportPage.vue?c3cc:36
callWithErrorHandling @ runtime-core.esm-bundler.js?f781:155
callWithAsyncErrorHandling @ runtime-core.esm-bundler.js?f781:164
emit @ runtime-core.esm-bundler.js?f781:718
eval @ runtime-core.esm-bundler.js?f781:7232
onClick @ QBtn.js?9c40:148
callWithErrorHandling @ runtime-core.esm-bundler.js?f781:155
callWithAsyncErrorHandling @ runtime-core.esm-bundler.js?f781:164
invoker @ runtime-dom.esm-bundler.js?9cec:366
这是我的 Vue 应用程序中的调用函数:
<template>
<v-btn design="alpha" @click="handleClick">loadData</v-btn>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import VBtn from 'src/components/VBtn.vue';
import { httpsCallable, FunctionsError } from 'firebase/functions';
import { functions } from 'src/config/firebase';
const data = ref();
const getZohoDeskTickets = httpsCallable(functions, 'getZohoDeskTickets');
const isFunctionsError = (error: unknown): error is FunctionsError => {
return (error as FunctionsError).details !== undefined;
};
const handleClick = async () => {
const ticket = await getZohoDeskTickets().catch((error) => {
if (isFunctionsError(error)) {
console.log(error.code);
console.log(error.message);
console.log(error.details);
} else {
console.log(error);
}
});
data.value = ticket;
console.log(ticket);
return ticket;
};
</script>
但即便如此我还是想不通。
无限循环的原因是什么?
或者可能是其他原因导致了这个错误?
终于明白了!
解决方案来自
简而言之;我需要像这样在返回的 axios 链上添加一个 .then()
:
export const getZohoDeskTickets = functions
.region('us-central1')
.https.onCall(async (data, context) => {
// Check if it passed App Check
if (context.app == undefined) {
throw new functions.https.HttpsError(
'failed-precondition',
'The function must be called from an App Check verified app.'
);
}
// Check the authentication
if (!context.auth) {
// Throwing an HttpsError so that the client gets the error details.
throw new functions.https.HttpsError(
'unauthenticated',
'The function must be called while authenticated.'
);
}
// Do the operation
const zohoAccessToken = await getSecretVersion(
'zoho-self-client-api-access-token'
).catch((error) => {
throw new functions.https.HttpsError('unknown', error.message, error);
});
return axios
.get('https://desk.zoho.com/api/v1/tickets', {
headers: {
orgId: '774638961',
Authorization: `Zoho-oauthtoken ${zohoAccessToken}`,
},
})
.then((response) => {
functions.logger.info(response.data);
return response.data;
})
.catch((error) => {
functions.logger.error(error.response.data);
throw new functions.https.HttpsError(
'unknown',
error.response.data.message,
error.response.data
);
});
});