不使用MongoDB时如何通过Meteor发布订阅获取同步数据
解决方案
你服务端发布时用的集合名是rooms,Meteor的DDP订阅机制会自动把服务端推送的added/changed事件同步到客户端本地缓存,你只需要在客户端声明一个同名的本地集合接收数据即可,不需要服务端有对应的Mongo持久化集合。
第一步:先修复现有代码的三处明显错误
- 服务端
_cache.add是错误写法,Map的新增元素方法是set,同时observers应该用Set类型方便增删,对应初始化代码改为:
if (!_cache.has(roomHash)) { _cache.set(roomHash, { messages:[], observers: new Set() }); }
- 服务端
pushMessage方法里room.messags拼写错误,改为room.messages - 客户端hook里
useTracker的依赖项orderHash是笔误,改为roomHash
第二步:客户端获取数据的实现
你提到的Meteor.Collection已在新版本Meteor中废弃,统一用Mongo.Collection,客户端声明的集合默认就是本地内存集合,不需要和后端Mongo绑定,直接用即可:
// 客户端全局声明同名集合,只在内存中存在,无需后端Mongo支持 const Rooms = new Mongo.Collection('rooms'); const useChatMessages = roomHash => { const { loading, messages } = useTracker(() => { const handle = Meteor.subscribe("chatroom", roomHash); const loading = !handle.ready(); // 从本地集合取对应房间的消息 const roomDoc = Rooms.findOne(roomHash); const messages = roomDoc ? roomDoc.messages : []; return { loading, messages }; }, [roomHash]); const pushMessage = useCallback(message => { Meteor.call('pushMessage', roomHash, message); }, [roomHash]); return { loading, messages, pushMessage }; };
如果你确实不想引入Mongo相关包
可以直接监听DDP消息自行维护状态,实现如下:
const useChatMessages = roomHash => { const [loading, setLoading] = useState(true); const [messages, setMessages] = useState([]); useEffect(() => { const handle = Meteor.subscribe("chatroom", roomHash, { onReady: () => setLoading(false) }); // 监听服务端推送的变更事件 const addedListener = (collection, id, fields) => { if (collection === 'rooms' && id === roomHash) { setMessages(fields.messages || []); } }; const changedListener = (collection, id, fields) => { if (collection === 'rooms' && id === roomHash && fields.messages) { setMessages(fields.messages); } }; Meteor.connection.on('added', addedListener); Meteor.connection.on('changed', changedListener); return () => { handle.stop(); Meteor.connection.off('added', addedListener); Meteor.connection.off('changed', changedListener); }; }, [roomHash]); const pushMessage = useCallback(message => { Meteor.call('pushMessage', roomHash, message); }, [roomHash]); return { loading, messages, pushMessage }; };
内容的提问来源于stack exchange,提问作者Yanick Rochon
相关产品推荐
相关产品推荐

