问题
In a Meteor app, a large collection containing 1000 records is published to the client. However users loading the {{loginButtons}
will experience a 3-5 second lag as it fully renders only after all the large collection loads.
It appears that the div #login-buttons
rendered by {{ loginButtons }}
is rendered instantly on page load, but the div #login-dropdown-list
is what's taking some time to start rendering. #login-dropodown-list template
The site is using Meteor 0.7.0.1 with Iron Router.
Update
Here's the template code for the accounts-ui-bootstrap-3
dropdown menu that take a few seconds to load after the rest of the page renders. It's just the basic template from the Meteor package, nothing special.
<ul class="nav navbar-nav navbar-right">
{{ loginButtons }}
</ul>
I used to think the problem is due to that this dropdown menu using the Meteor.users
collection, so here's my Fast Render route.
FastRender.onAllRoutes(function(urlPath) {
this.subscribe(Meteor.users);
this.subscribe(users);
})
This does not seem to help with the problem. I also found out that Meteor.userId()
is already defined when the dropdown menu is still not rendered. The dropdown menu only appears/renders at the point in time pointed to by the red arrow, which is the point where all the collections have loaded.
Furthermore, the div #login-buttons
rendered by {{ loginButtons }}
is rendered instantly on page load, but the div #login-dropdown-list
is what's taking some time to start rendering.
Maybe it's how accounts-ui-bootstrap-3
handles the rendering?

回答1:
You can use iron-router's waiton
on specific routes and loadingTemplate
properties to show the user a progress indicator while the subscription gets ready. As seen on https://github.com/EventedMind/iron-router#waiting-on-subscriptions-waiton
Router.configure({
layoutTemplate: 'layout',
notFoundTemplate: 'notFound',
loadingTemplate: 'loading'
});
Router.map(function () {
this.route('postShow', {
path: '/posts/:_id',
waitOn: function () {
return Meteor.subscribe('posts');
}
});
});
Also, https://atmosphere.meteor.com/package/fast-render is a third party package which integates into iron-router and sends down the initial data along with the template therefore making the page appear loaded with data instantly.
There is a good tutorial about this at http://meteorhacks.com/integrating-iron-router-based-apps-with-fast-render.html
回答2:
I see two other packages that could help you :
Paginated subscription : https://atmosphere.meteor.com/package/paginated-subscription The idea here would be to set a small limit for the initial load, and when the rest is loaded, change the limit to load the rest
Lazy subscription : https://atmosphere.meteor.com/package/lazy-subscription The idea here is not to subscribe at all to your large collection in the first time ; only init it like that :
Post = new Meteor.Lazy('post', function() { Meteor.subscribe('posts'); });
(it does not subscribe to anything)
And then when ready : Template.some_template.get_posts = function() { return Post().find({}); //Note that Post is now a function. }; => it doe subscribe
The second solution may seem more straight forward, but you can manage it way better with the first one.
来源:https://stackoverflow.com/questions/21886969/loading-a-large-collection-in-a-meteor-app