Node.js+Express中请求内实现FCM通知入库不生效如何解决
问题根本原因
- 核心逻辑错误:你在
fcm.send的成功回调内部动态声明app.post("/notfs")路由,路由声明仅用于注册接口规则,必须在服务启动阶段完成,不能写在接口请求处理逻辑中。声明该路由后不会自动触发执行,因此数据库写入逻辑从来没有被调用过。 - 异步逻辑混乱:外层
/fcm接口用了async声明,内部fcm.send用回调写法,嵌套逻辑容易遗漏异常捕获,也没有在逻辑处理完后给请求方返回响应。
修复实现
你不需要额外定义POST /notfs接口来存储通知,直接在FCM发送成功后执行数据库写入即可,修复后的完整代码如下:
var FCM = require("fcm-node"); const express = require("express"); const mongoose = require("mongoose"); require("dotenv/config"); const app = express(); app.use(express.json()); // 扩展通知表字段,存储更完整的信息 const notificationSchema = mongoose.Schema({ title: String, body: String, targetToken: String, sendStatus: { type: String, enum: ['success', 'fail'], default: 'success' }, fcmMsgId: String, createTime: { type: Date, default: Date.now } }); const NotificationModel = mongoose.model("Notification", notificationSchema); // 封装fcm.send为promise,适配async/await写法 function sendFcmPromise(fcm, message) { return new Promise((resolve, reject) => { fcm.send(message, (err, res) => { if (err) return reject(err); resolve(res); }) }) } app.post("/fcm", async (req, res, next) => { const { token, title, body } = req.body; // 可自行补充参数非空校验逻辑 let sendResult = null; let sendStatus = 'success'; try { const fcm = new FCM(process.env.SERVER_KEY); const message = { to: token, notification: { title, body }, }; sendResult = await sendFcmPromise(fcm, message); } catch (err) { sendStatus = 'fail'; next(err); } finally { // 无论发送成功失败都存入数据库,方便排查 const newNotf = new NotificationModel({ title, body, targetToken: token, sendStatus, fcmMsgId: sendResult?.results[0]?.message_id || null }); await newNotf.save(); } res.json({ code: 200, msg: '通知发送完成', data: sendResult }) }); app.get("/notfs", async (req, res) => { const notfs = await NotificationModel.find().sort({ createTime: -1 }); res.send(notfs); }); mongoose .connect(process.env.CONNECTION_STRING) .then(() => console.log("数据库连接成功")) .catch((err) => console.log("数据库连接失败", err)); app.listen(3000, () => console.log("服务启动,监听3000端口"));
优化点说明
- 用Promise封装回调形式的fcm.send方法,统一用async/await处理异步逻辑,避免回调嵌套
- 扩展通知表字段,存储通知标题、目标设备token、发送状态、FCM返回的消息ID、发送时间,方便后续排查问题和历史追溯
- 新增finally逻辑,无论通知发送成功还是失败都写入数据库,完整记录所有请求
- 补充请求响应返回,调用方可以明确知道请求处理结果
- 查询历史通知接口新增按时间倒序排序,最新发送的通知排在最前面
内容的提问来源于stack exchange,提问作者user16029178
相关产品推荐
相关产品推荐

