如何在Firebase实时数据库云函数中实现表情化后触发通知
必须先完成表情化,再触发通知!
Cloud Functions的数据库触发是异步分布式执行的,如果让两个函数同时触发(一个监听/adminChat的onCreate,一个监听message的onWrite),完全无法保证执行顺序——大概率会出现通知先发送,而表情化还没完成的情况,导致用户收到的是原始文本通知。
下面给你两种靠谱的实现方案,根据你的业务需求选就行:
方案1:调整通知函数的触发节点,监听表情化完成后的结果
这种方案通过数据库节点的依赖关系,让通知只在表情化完成后触发,耦合度低,适合需要保留两个独立函数的场景。
场景A:表情化函数覆盖原message节点
如果你的emojify是直接把原始文本替换成表情化文本,那通知函数可以监听message的onUpdate事件,并且只在确认是表情化更新时触发:
// 原表情化函数(保留逻辑,加个重复触发判断) exports.emojify = functions.database.ref('/adminChat/{adminChatUid}/message') .onWrite(async (change, context) => { const originalText = change.before.val(); // 避免重复触发:如果已经是表情化文本(假设包含表情),直接返回 if (!originalText || change.after.val().match(/[\u{1F600}-\u{1F64F}]/u)) { return null; } // 示例表情化逻辑 const emojifiedText = originalText .replace(/hello/gi, '👋 Hello') .replace(/thanks/gi, '🙏 Thanks'); await change.after.ref.set(emojifiedText); return null; }); // 修改后的通知函数:监听message的更新事件 exports.sendAdminGroupNotification = functions.database.ref('/adminChat/{adminChatUid}/message') .onUpdate(async (change, context) => { const emojifiedText = change.after.val(); const adminChatUid = context.params.adminChatUid; // 这里写你的通知逻辑,比如发送FCM console.log(`给管理员组发送通知:${emojifiedText}`); // const fcmMessage = { // notification: { title: '新管理员消息', body: emojifiedText }, // topic: 'admin-group' // }; // await admin.messaging().send(fcmMessage); return null; });
场景B:表情化函数写入新的emojifiedMessage节点
如果想保留原始文本,把表情化结果存在独立节点,那通知函数直接监听这个新节点的onCreate即可:
// 修改后的表情化函数:写入独立节点 exports.emojify = functions.database.ref('/adminChat/{adminChatUid}/message') .onCreate(async (snapshot, context) => { const originalText = snapshot.val(); const emojifiedText = originalText .replace(/hello/gi, '👋 Hello') .replace(/thanks/gi, '🙏 Thanks'); // 写入新的表情化节点 await snapshot.ref.parent.child('emojifiedMessage').set(emojifiedText); return null; }); // 通知函数:监听表情化节点的创建事件 exports.sendAdminGroupNotification = functions.database.ref('/adminChat/{adminChatUid}/emojifiedMessage') .onCreate(async (snapshot, context) => { const emojifiedText = snapshot.val(); const adminChatUid = context.params.adminChatUid; // 执行通知发送逻辑 console.log(`给管理员组发送通知:${emojifiedText}`); // ... 你的FCM发送代码 return null; });
方案2:在表情化函数内直接调用通知逻辑
如果你的业务逻辑不需要拆分两个独立函数,这种方案最直接,完全保证顺序,没有任何异步竞态问题:
// 合并逻辑:先完成表情化,再发送通知 exports.emojifyAndNotify = functions.database.ref('/adminChat/{adminChatUid}/message') .onCreate(async (snapshot, context) => { // 步骤1:执行表情化 const originalText = snapshot.val(); const emojifiedText = originalText .replace(/hello/gi, '👋 Hello') .replace(/thanks/gi, '🙏 Thanks'); // 可选:覆盖原message,或写入新节点 await snapshot.ref.set(emojifiedText); // 步骤2:发送通知 const adminChatUid = context.params.adminChatUid; console.log(`给管理员组发送通知:${emojifiedText}`); // ... 你的FCM通知发送代码 return null; });
内容的提问来源于stack exchange,提问作者Ticherhaz FreePalestine
相关产品推荐
相关产品推荐

