Javascript 当订阅已限制数据集时,是否需要传递数据限制?
在一个关于分页的示例中,根据应显示多少个结果向路由传递不同的编号Javascript 当订阅已限制数据集时,是否需要传递数据限制?,javascript,meteor,iron-router,Javascript,Meteor,Iron Router,在一个关于分页的示例中,根据应显示多少个结果向路由传递不同的编号 // 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
// 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})
};
}
});
我想知道是否仍有必要在data属性中提供Posts.find()参数。这里似乎有点多余,因为waitOn中的subscribe已经限制了我从服务器返回的数据集。我知道数据用于为模板的不同部分提供数据上下文。但是,在这里为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');
}
}
这只会在控制台中输出“尚未就绪”,即使页面加载完成,也不会更改
非常感谢你的帮助
编辑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集合中。在这种情况下,如果省略了查询参数,那么最终将得到不可预测的结果。更多信息请参阅。还请注意,虽然
iron:router
支持在路由处理程序中进行订阅,但可以在模板生命周期方法中处理它们
对于第二个问题,Posts集合显示为空的原因是文件顶层的代码在加载文件时立即运行。此时,集合订阅尚未加载,因此前端集合为空。您需要在一些被动上下文中检查订阅准备情况,例如模板帮助程序或Tracker.autorun
,以确保数据已加载:
var handle=Meteor.subscribe('posts');
if(handle.ready()){
//这将记录帖子的实际数量
log(Posts.find().count());
}否则{
//此日志记录0(除非此集合有其他订阅)
log(Posts.find().count());
}
第一部分非常有意义。但是,在第二部分中,我尝试使用ready()函数,但没有显示任何结果。我在问题中添加了新代码。是不是因为我没有在计算中包装反应源?我试着将它包装在Tracker.autorun中,结果它成功了。@wheals是的,这就是问题所在。Meteor反应性在反应性上下文中调用反应性函数(如subscriptionHandle.ready()
)时起作用,如Tracker.autorun
,一个模板助手,属于iron:router
路由定义。在这些函数之外,Meteor无法重新运行代码,因为它的反应数据源发生了变化。