当订阅已经限制了数据集时,是否有必要将限制传递给数据?

Necessary to pass limit to data when subscription already limits the dataset?

在有关分页的示例中,根据应显示的结果数量,将不同的数字传递给路由。

//   lib/router.js
Router.route('/:postsLimit?', {
  name: 'postsList',
  waitOn: function() {
    var limit = parseInt(this.params.postsLimit) || 5; 
    return Meteor.subscribe('posts', {sort: {submitted: -1}, limit: limit});
  },
  data: function() {
    var limit = parseInt(this.params.postsLimit) || 5; 
    return {
      posts: Posts.find({}, {sort: {submitted: -1}, limit: limit})
    };
  }
});

我想知道是否还有必要在数据属性中提供 Posts.find() 参数。这里似乎有点多余,因为 waitOn 中的订阅已经限制了我从服务器返回的数据集。我知道数据用于为我的模板的不同部分提供数据上下文。然而,在这里为 data Posts.find() 提供相同的参数似乎是多余的。我试过只使用不带参数的 Posts.find() 并且它有效。

另外,我想知道访问路由器中所有数据的方法是什么?我正在访问单个路由之外的 Posts 集合,我认为我能够访问 Posts 集合中的所有数据。但是,它返回的计数为 0。

//    lib/router.js
var totalPostsCount = Posts.find().count()
console.log('total count?')
console.log(totalPostsCount)       //  output 0


PostsListController = RouteController.extend({
  template: 'postsList',
  increment: 5, 
  postsLimit: function() { 
    return parseInt(this.params.postsLimit) || this.increment; 
  },
  findOptions: function() {
    return {sort: {submitted: -1}, limit: this.postsLimit()};
  },
  subscriptions: function() {
    this.postsSub = Meteor.subscribe('posts', this.findOptions());
  },
  posts: function() {
    // console.log("is find limited to subscriptions too??");
    // console.log(Posts.find().count())
    return Posts.find({}, this.findOptions());
  },
  data: function() {
    // console.log('is data limited to this?')
    // console.log(Posts.find().count())

    var hasMore = this.posts().count() === this.postsLimit();
    var adjustOrNot = this.posts()
    if (!hasMore){
        var nextPath = this.route.path({postsLimit: this.posts().count()});     
    }else{
        var nextPath = this.route.path({postsLimit: this.postsLimit() + this.increment});       
    }
    return {
      posts: this.posts(),
      ready:this.postsSub.ready(),
      nextPath: hasMore ? nextPath : null
    };
  }
});

//...

Router.route('/:postsLimit?', {
  name: 'postsList'
});

编辑 1:获取所有帖子的代码:

// server
Meteor.publish('allPosts',function(){

    return Posts.find({});
})


// lib/router.js
if (Meteor.isClient){
    var handle = Meteor.subscribe('allPosts');
    if (handle.ready()) {
      // This logs the actual count of posts
      console.log(Posts.find().count());
    } else {

      console.log('not ready yet');
    }
}

这只会在控制台中输出 'not ready yet',即使页面加载完成也不会改变。

非常感谢您的帮助。

编辑 2:可能的解决方案

我尝试将反应源 ready() 包装在诸如 Tracker.autorun() 之类的计算中,现在它起作用了。

if (Meteor.isClient){
    var handle = Meteor.subscribe('allPosts');

    Tracker.autorun(function(){
        var status = handle.ready();
        if (status){
            console.log(Posts.find().count())
        }else{
            console.log('not ready yet')
        }
    })

}

是的,无论您的订阅如何,您也应该将限制和其他查询选项传递给前端查询。这是因为如果您要同时激活对同一个集合的多个订阅(在大型应用程序中经常这样做),那么订阅的记录最终都会在前端的同一个 Minimongo 集合中。在这种情况下,如果您省略了查询参数,您最终会得到不可预知的结果。在 this excellent explanation. Note also that while iron:router supports doing subscriptions in the route handlers, it's encouraged 中查看更多信息以在模板生命周期方法中处理它们。

对于您的第二个问题,Posts 集合显示为空的原因是文件顶层的代码在加载文件时立即 运行。此时集合订阅还没有加载,所以前端集合是空的。您需要在一些反应性上下文中检查订阅准备情况,例如模板助手或 Tracker.autorun,以确保数据已加载:

var handle = Meteor.subscribe('posts');
if (handle.ready()) {
  // This logs the actual count of posts
  console.log(Posts.find().count());
} else {
  // This logs 0 (unless there are other subscriptions to this collection)
  console.log(Posts.find().count());
}