Firebase Cloud Functions报错TypeError: handler is not a function求助
解决Firebase Cloud Functions部署后
TypeError: handler is not a function错误 错误原因
你的核心问题出在函数导出的重复包装:
- 在
sendPoke.js文件中,已经通过exports.sendPoke = functions.https.onCall(...)创建了一个合法的可调用函数实例。 - 但在
index.js中,你再次用functions.https.onCall(sendPoke)对它进行包装,导致Firebase收到的不是预期的处理函数,而是嵌套的无效对象,最终抛出handler is not a function错误。
另外还有一个潜在问题:admin.messaging().sendToDevice需要的是用户的FCM注册令牌,而非Firebase Auth的UID,直接传入UID会导致通知发送失败。
解决方案
- 修正
index.js的导出逻辑,直接复用sendPoke.js中已定义的可调用函数。 - 调整
sendPoke.js的逻辑,通过用户UID查询对应的FCM令牌后再发送通知。
修正后的代码
1. sendPoke.js(函数逻辑修正)
const functions = require("firebase-functions"); const admin = require("firebase-admin"); exports.sendPoke = functions.https.onCall(async (data, context) => { const sentBy = context.auth?.uid; // 接收用户UID,后续通过UID查询FCM令牌 const recipientUid = data.recipientUid; const message = data.message || "Seni dürttü!"; if (!sentBy || !recipientUid) { throw new functions.https.HttpsError( "invalid-argument", "发送者和接收者的UID不能为空。" ); } try { // 从Firestore获取接收者的FCM令牌(假设你有users集合,存储了fcmToken字段) const userDoc = await admin.firestore().collection("users").doc(recipientUid).get(); if (!userDoc.exists || !userDoc.data()?.fcmToken) { throw new functions.https.HttpsError( "not-found", "接收者未绑定有效的FCM令牌。" ); } const fcmToken = userDoc.data().fcmToken; const payload = { notification: { title: "新的戳一戳!", body: `${sentBy} 戳了你一下!`, }, data: { sentBy, recipientUid, message, }, }; // 使用FCM令牌发送通知 const response = await admin.messaging().sendToDevice(fcmToken, payload); console.log("通知发送成功:", response); return { success: true, message: "戳一戳已发送。" }; } catch (error) { console.error("发送失败:", error); throw new functions.https.HttpsError("unknown", "发送过程中出现错误。"); } });
2. index.js(导出逻辑修正)
const functions = require("firebase-functions"); const admin = require("firebase-admin"); if (!admin.apps.length) { admin.initializeApp(); } // 直接导出sendPoke.js中已定义的可调用函数,无需再次包装 exports.sendPoke = require("./functions/utilities/pokeAndNotifications/sendPoke").sendPoke;
3. Flutter端调用代码修正
import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:cloud_functions/cloud_functions.dart'; Future<void> sendPokeNotification(String recipientUid) async { try { final HttpsCallable callable = FirebaseFunctions.instance.httpsCallable('sendPoke'); final response = await callable.call<String, dynamic>({ "recipientUid": recipientUid, // 传入接收者的UID "message": 'Hi, i poked you!', }); print('函数响应: ${response.data}'); } catch (e) { print('发送错误: $e'); } }
部署验证
修改完成后,重新执行部署命令:
firebase deploy --only functions
内容的提问来源于stack exchange,提问作者Yasin G.
相关产品推荐
相关产品推荐

