Firebase云函数推送通知成功却触发60秒超时错误排查
问题排查:Firebase云函数FCM推送成功但超时报错
问题概述
Firebase云函数可正常通过FCM Token推送通知(标题和内容正确),但日志显示函数执行耗时60000ms后状态为'error',实际推送任务仅耗时约0.6秒。
相关代码
require("firebase-functions/logger/compat"); const functions = require("firebase-functions"); const admin = require("firebase-admin"); // to get the ADC automatically admin.initializeApp({credential: admin.credential.applicationDefault()}); exports.pushNotificationPulse = functions.https.onRequest((request, response) => { console.log("Push notification event triggered [Function last updated 28/06/23]"); const firstName = request.query.fullName.split(" ")[0]; const FCMtoken = request.query.FCM_Token; let msg = request.query.msg; if (msg == "") { msg = "DEFAULT MSG IF NOT PROVIDED"; } const message = { notification: { title: "TEXT HERE", body: msg, }, token: FCMtoken, }; admin .messaging() .send(message) .then((response) => { console.log(`Successfully sent message: ${response}`); return {status: `Successfully sent message: ${response}`}; }) .catch((error) => { console.log(`Error sending message: ${error}`); return {status: `Error sending message: ${error}`}; }); });
日志信息
2023-06-28T13:43:08.151324506Z D pushNotificationPulse: Function execution started 2023-06-28T13:43:08.201451Z I pushNotificationPulse: Push notification event triggered [Function last updated 28/06/23] 2023-06-28T13:43:08.810690Z I pushNotificationPulse: Successfully sent message: projects/toy-app-80345/messages/1687959788647301 2023-06-28T13:44:08.152258848Z D pushNotificationPulse: Function execution took 60000 ms, finished with status: 'error'
问题原因与修复方案
核心问题
这是典型的HTTPS云函数未返回响应导致的超时错误。FCM推送确实成功完成,但函数没有向请求方发送任何响应,Firebase会等待60秒的默认超时时间后强制终止函数,并标记为error状态。此外原代码中then回调的参数名response与外部的请求响应对象重名,会导致变量覆盖问题。
修复代码
修改函数,在推送完成(成功或失败)后通过response对象返回结果:
require("firebase-functions/logger/compat"); const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp({credential: admin.credential.applicationDefault()}); exports.pushNotificationPulse = functions.https.onRequest((request, response) => { console.log("Push notification event triggered [Function last updated 28/06/23]"); const firstName = request.query.fullName.split(" ")[0]; const FCMtoken = request.query.FCM_Token; let msg = request.query.msg; if (msg == "") { msg = "DEFAULT MSG IF NOT PROVIDED"; } const message = { notification: { title: "TEXT HERE", body: msg, }, token: FCMtoken, }; admin .messaging() .send(message) .then((sendResponse) => { console.log(`Successfully sent message: ${sendResponse}`); // 发送成功响应 response.status(200).send({status: `Successfully sent message: ${sendResponse}`}); }) .catch((error) => { console.log(`Error sending message: ${error}`); // 发送错误响应 response.status(500).send({status: `Error sending message: ${error}`}); }); });
关键修改点
- 重命名
then回调中的参数为sendResponse,避免覆盖外部的请求响应对象 - 在
then和catch中分别调用response.status().send(),向请求方返回对应的HTTP状态码和结果 - 确保函数在异步操作完成后立即结束,不会触发超时
可选优化:使用async/await写法
如果习惯更清晰的异步代码风格,可以改用async/await:
require("firebase-functions/logger/compat"); const functions = require("firebase-functions"); const admin = require("firebase-admin"); admin.initializeApp({credential: admin.credential.applicationDefault()}); exports.pushNotificationPulse = functions.https.onRequest(async (request, response) => { console.log("Push notification event triggered [Function last updated 28/06/23]"); try { const firstName = request.query.fullName.split(" ")[0]; const FCMtoken = request.query.FCM_Token; let msg = request.query.msg; if (msg == "") { msg = "DEFAULT MSG IF NOT PROVIDED"; } const message = { notification: { title: "TEXT HERE", body: msg, }, token: FCMtoken, }; const sendResponse = await admin.messaging().send(message); console.log(`Successfully sent message: ${sendResponse}`); response.status(200).send({status: `Successfully sent message: ${sendResponse}`}); } catch (error) { console.log(`Error sending message: ${error}`); response.status(500).send({status: `Error sending message: ${error}`}); } });
内容的提问来源于stack exchange,提问作者Bradley Cable
相关产品推荐
相关产品推荐

