1

如果存在某些内容,我正在尝试路由到一个页面,如果不存在,我正在尝试路由到另一个页面。但是,我不想订阅整个集合(〜千),因为我认为它会影响性能。我该怎么做呢?

我尝试过这样的事情,但由于某种原因,Meteor 在页面加载时会两次遍历路由器代码,并在重定向到项目页面之前短暂闪烁错误页面,我不希望这种情况发生。

这是我所拥有的:

路由器.coffee

to: (id)->
  Meteor.subscribe 'item', id
  item = Items.findOne id
  if item
    # if the item exists, then redirect to it
    Session.set 'currentItemId', id
    'itemPage'
  else
    # if not, then redirect to the sorry page
    'sorryPage'

出版物.咖啡

Meteor.publish 'item', (id)->
  return Items.find({_id: id})

订阅整个集合会影响性能,对吗?有没有更简单的方法来检查集合中的存在而不订阅它?我试图做一个 Meteor.call 来检查它的服务器端,但它没有工作并且不理想(路由器等待服务器调用..)。有没有“正确”的方法来做到这一点?

4

1 回答 1

1

您获得这种“闪烁”效果的原因可能是因为您的路由器被实现为反应式(我不确定这是否是正确的策略顺便说一句),并且由于您使用的是Items.findOne,因此此方法会使当前计算立即失效当请求的数据Meteor.subscribe到达Items集合时。

另外,请注意,一旦重新计算计算,活动计算中的每个订阅都会自动取消。但是,正如文档中所声称的那样(看这里Meteor应该足够聪明,可以检测到您何时订阅相同的数据集两次,所以这不应该有任何副作用。

如果我是你,我会考虑将我的路由器逻辑更改为这样的:

Session.set('currentItemId', id);
var status = Session.get('currentItemStatus');    
if (status === 'ready')
    return 'itemPage';
if (status === 'missing')
    return 'sorryPage';
return 'loadingPage'; // probably status === 'loading'

然后,在项目的其他地方我会做:

Deps.autorun(function () {
    Session.set('currentItemStatus', 'loading');  
    Meteor.subscribe('item', Session.get('currentItemId'), function () {
        // onReady callback
        var item = Items.findOne({_id:id});
        if (item)
            Session.set('currentItemStatus', 'ready');
        else
            Session.set('currentItemStatus', 'missing');
    });
});

请注意,如果currentItemId不改变,定义的计算Deps.autorun不会失效,因此不会loadingPage向用户显示不必要的。

于 2013-10-21T12:49:04.237 回答