Meteor 1.2.0.1发布/订阅问题

时间:2015-09-24 18:25:58

标签: mongodb meteor publish-subscribe

在Meteor应用程序中,发布到服务器上的集合的数据未显示在客户端中。

从默认的Meteor应用程序开始,我将默认的JavaScript文件更改为以下内容:

Test = new Mongo.Collection("test")

if (Meteor.isClient) {
  Meteor.subscribe("test")
  console.log(Test.find({}).fetch())
}

if (Meteor.isServer) {
  Meteor.startup(function () {
    Meteor.publish("test", function () {
      var cursor = Test.find({})
      var result = cursor.fetch()
      console.log(result)
      console.log(JSON.stringify(result))
      return cursor
    })

    var selector = {}
    var modifier = { key: "value" }
    var options = {}
    var callback = function (error, data) {
      console.log("Test", error, data)
    }
    Test.upsert( selector, modifier, options, callback )
  });
}

在服务器终端中,我可以看到文档已添加到Test集合中,并且该集合现在包含文档,但浏览器中console.log(Test.find({}).fetch())的输出为[]

这是服务器的典型输出:

I20150924-14:38:59.313(-4)? Test null { numberAffected: 1 }
=> Meteor server restarted
I20150924-14:38:59.404(-4)? [ { _id: 'e3B6js9xq3pbspego', key: 'value' } ]
I20150924-14:38:59.405(-4)? [{"_id":"e3B6js9xq3pbspego","key":"value"}]

来自浏览器:

Navigated to http://localhost:3000/
[]                   mongoTest.js:5 

我错过了什么?

2 个答案:

答案 0 :(得分:1)

这是预期的,因为subscribe不会阻止浏览器的执行。订阅开始后,Test.find()在文档到达客户端之前执行。这是一个应该打印结果的实现:

if (Meteor.isClient) {
  Meteor.subscribe('test', function() {
    console.log(Test.find({}).fetch());
  });
}

更强大的解决方案是使用autorun,因为它可以避免添加第一个文档的任何竞争条件:

var handle = Meteor.subscribe('test');

Tracker.autorun(function() {
  if (handle.ready())
    console.log(Test.find({}).fetch());
});

推荐阅读:common mistakes的“订阅不会阻止”部分。

答案 1 :(得分:0)

Tracker.autorun(...)添加到客户端代码可以解决问题:

if (Meteor.isClient) {
  Tracker.autorun(function () {
    Meteor.subscribe("test")
    console.log(Test.find({}).fetch())
  })
}

浏览器控制台中的输出现在是:

Navigated to http://localhost:3000/
[]                   mongoTest.js:6
v [Object]           mongoTest.js:6
  > 0: Object
      _id: "e3B6js9xq3pbspego"
      key: "value"
    length: 1
  > __proto__: Array[0]

当客户端首次连接到服务器时,显然Test.find({}).fetch()找到一个空集合,然后服务器有时间更新客户端上的集合。