Meteor Publish + Reactive查询对象

时间:2015-05-23 21:01:49

标签: javascript mongodb meteor

请考虑以下事项:

在我的客户端上,我构建了一个复杂的过滤器,该过滤器保存在名为currentFilter的自定义反应对象中。

currentFilter.buildQuery()返回我用来查询mongodb数据库的对象。

由于服务器上mongodb数据库中的数据量很大,我想过滤服务器端的数据,并只发布客户端所需的数据。

我的代码如下:

//CLIENT

// file = a.html

<template name="myTemplate">
  {{data}}
</template>

//file = a.js

cbs = new Mongo.Collection('cbsLoc');

Template.myTemplate.helpers({

    data: function () {
        Tracker.autorun(function () {
            Meteor.subscribe('cbsLoc',currentFilter.buildQuery())

        });

        return cbs.find()    // (a)
    }
})

//SERVER

Meteor.publish('cbsLoc', function(filter) {
    return cbs.find(filter)
});

cbs.find()将返回数据以填充表格。不幸的是它没有用。虽然数据确实返回给客户端,但它并没有显示在dom。

如果我将(a)处的行更改为cbs.find().fetch(),它的效果会完美(即它会显示在dom中)。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:0)

我已将此作为回答,因为其中包含一些代码 - 在评论中难以阅读。

我唯一能想到的是,在光标的情况下,当模板显示时它没有准备好,而我似乎记得在fetch()的情况下,流星会等到一切都到了

尝试一些防御性编码,例如:

data: function () {
   Tracker.autorun(function () {
       Meteor.subscribe('cbsLoc',currentFilter.buildQuery())
   });
   var cursor = cbs.find();
   if(cursor) 
       return cbs.find()    // (a)
}

如果那不想工作,那么也许你应该将数据转移到路由器(如果你有铁路由器),你可以将订阅部分放在waitOn()或subscriptions()中函数,通常是订阅的位置。

答案 1 :(得分:0)

这是我的解决方案。

我将订阅移到了onCreated()回调中。我的最后一段代码如下:

//CLIENT

// file = a.html

<template name="myTemplate">

    {{#if Template.subscriptionsReady}}
        {{> reactiveTable class="table table-bordered table-hover table-responsive" collection=cbListings settings=settings}}
    {{else}}
        {{>loading}}
    {{/if}}

</template>

//file = a.js

cbs = new Mongo.Collection('cbsLoc');

Template.myTemplate.onCreated(function () {
    var self = this;

    self.autorun(function () {

        self.subscribe('cbs', currFilter.buildQuery());

    });

    self.cbListings = function(){
        return cbs.find();
    }

});

Template.myTemplate.helpers({

    cbListings: function() {

        return Template.instance().cbListings();
    }
});

//SERVER

Meteor.publish('cbsLoc', function(filter) {
    return cbs.find(filter)
});

感谢David Weldon和mwarren指出我的正确选择。

该解决方案基于docs here以及此blog post

顺便说一句,这仅适用于{{#if Template.subscriptionsReady}},如此:

{{#if Template.subscriptionsReady}}
    {{> reactiveTable class="table table-bordered table-hover table-responsive" collection=cbListings settings=settings}}
{{else}}
    {{>loading}}
{{/if}}

对我而言,这种模式的作用并不明显。我的困惑在于onCreatedhelper回调之间的关系:

1)

在页面加载时,self.cbListingsnull(这对我来说很有意义)

2)

在此之后,我们由助手创建cbListings,但它通过Template.instance().cbListings()代码返回对自身的引用。

有了上述内容,这里发生了什么?

此外,如果Template.instance().cbListings()尚未创建第一次创建错误,这怎么也不会出错。我知道这是因为如果我在self.cbListings回调中打印onCreated,则输出会给我未定义。但如果我在self.cbListings内执行此操作,我将获得输出= function()(我使用的是萤火虫)。

3)

最后,虽然onCreated回调只运行一次,但Template.subscriptionsReady正在设法执行self.cbListings = function(){return cbs.find()}cbListings创建helper后执行的操作}。这是怎么回事?