Ember.js结合Firebase开发聊天,数据库新增消息后如何实时更新?
问题原因
你当前使用的Ember Data findAll('chat-message') 是一次性查询方法,仅会在路由加载时拉取一次历史消息,没有监听Firebase的实时数据推送事件。当其他客户端发送新消息到Firebase后,本地Ember Store不会自动同步新数据,因此绑定了Store数据的页面不会自动刷新。
解决方案
核心是给聊天消息集合添加Firebase实时监听器,监听到新消息后主动同步到本地Ember Store,借助Ember的响应式能力自动刷新页面。你不需要修改现有模板代码,仅需要调整路由层的逻辑:
1. Cloud Firestore 版本适配
修改routes/show-messages.js代码如下:
//routes/show-messages.js import Route from '@ember/routing/route'; import { inject as service } from '@ember/service'; export default class ShowMessagesRoute extends Route { @service store; @service firebase; // 保存取消监听的函数,旧版Ember可改为普通属性不用#前缀 #unsubscribeListener = null; async model() { // 先拉取历史消息初始化Store await this.store.findAll('chat-message'); const db = this.firebase.firestore(); // 开启消息集合的实时变更监听 this.#unsubscribeListener = db.collection('chat-messages').onSnapshot(snapshot => { snapshot.docChanges().forEach(change => { // 仅处理新增的消息 if (change.type === 'added') { // 将Firebase返回的新消息同步到本地Ember Store this.store.push({ data: { id: change.doc.id, type: 'chat-message', attributes: change.doc.data() } }); } }); }); // 返回Store中的消息集合,是响应式对象,数据变更会自动触发模板更新 return this.store.peekAll('chat-message'); } // 路由离开时销毁监听,避免内存泄漏 deactivate() { if (this.#unsubscribeListener) { this.#unsubscribeListener(); } } }
2. 实时数据库(Realtime Database)版本适配
如果你使用的是Firebase实时数据库而非Cloud Firestore,将上述监听逻辑替换为以下代码即可:
const dbRef = this.firebase.database().ref('chat-messages'); this.#unsubscribeListener = dbRef.on('child_added', snapshot => { this.store.push({ data: { id: snapshot.key, type: 'chat-message', attributes: snapshot.val() } }); }); // 对应取消监听的逻辑调整为 // deactivate() { // if (this.#unsubscribeListener) { // this.firebase.database().ref('chat-messages').off('child_added', this.#unsubscribeListener); // } // }
注意事项
- 确保你项目中
app/models/chat-message.js里定义的属性和你存入Firebase的字段(text、username等)完全对应,否则同步到Store的时候会丢失字段 - 你现有的
ChatInput组件不需要修改,只要它能正确把消息写入Firebase,监听器就会自动捕获到新数据同步到所有在线客户端
内容的提问来源于stack exchange,提问作者OlofSvahn
相关产品推荐
相关产品推荐

