You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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会导致通知发送失败。

解决方案

  1. 修正index.js的导出逻辑,直接复用sendPoke.js中已定义的可调用函数。
  2. 调整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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 16:10:14