【发布时间】:2016-09-06 06:41:41
【问题描述】:
经过大量阅读,我开始更好地处理 Meteor 的发布/订阅模型。我已经从我的第一个应用程序中删除了自动发布训练轮,虽然我几乎可以正常工作,但我发现了一个问题。
当应用首次加载时,我的发布和订阅钩子运行良好。我有一个在Tracker.autorun() 块中运行的代码块,它进行订阅调用,我可以在订阅句柄上使用ready() 顺序等待来自服务器的数据,等等。
我的应用程序的一个特点是它允许用户将新文档插入到集合中。更具体地说,当用户执行某个操作时,这会触发插入。此时,客户端 JS 运行,并且插入 MiniMongo 完成。反应式autorun 块运行,客户端可以看到插入的文档。客户端使用新插入的数据更新 DOM,一切正常。
此外,当我查看服务器端 MongoDB 时,我看到了插入的文档,这意味着服务器端 JS 也运行良好。
这就是奇怪的地方。客户端 autorun 块第二次运行(我不知道为什么),这一次,客户端不再有插入的项目。当 DOM 呈现时,新插入的项目现在消失了。如果我重新加载页面,一切都会恢复正常。
以前有人见过这种行为吗?我还注意到服务器端发布调用在页面加载时运行一次,但在插入后它不会再次运行。这似乎是错误的,因为客户端在插入之后(即在 Meteor 的客户端延迟补偿之后)如何从服务器获取协调后的数据?
重要的功能(ComponentInstances 是被窃听的集合):
发布块:
Meteor.publish('allComponentInstances', function (documentId, screenIndex) {
console.log(`documentId: ${documentId} screenIndex: ${screenIndex}`)
const screens = Screens.find({ownerDocumentId: documentId})
const selectedScreen = screens.fetch()[screenIndex]
return ComponentInstances.find({_id: {$in: selectedScreen.allComponentInstanceIds}})
})
autorun中的订阅块:
// ... a bunch of irrelevant code above
const allComponentInstancesHandle = Meteor.subscribe('allComponentInstances', document._id, 0)
if (allComponentInstancesHandle.ready()) {
isReady = true
screens = Screens.find({ownerDocumentId: document._id}).fetch()
const componentInstanceObjects = ComponentInstances.find().fetch()
allComponentInstances = {}
componentInstanceObjects.map((componentInstance) => {
allComponentInstances[componentInstance._id] = componentInstance
})
}
【问题讨论】: