Let’s say you’re building a Twitter client for the web. You have a pretty standard setup:
App.Router.map(function() {
this.resource('tweets', { path: '/tweets/:id' });
});
The TweetsIndexRoute
fetches a tweet by ID and connects it to the controller and, in turn, the view. All is well.
Then your product designers come up with a new feature: “suggested follow.” When you’re looking at a tweet, the app shows a list of people you might want to follow in the sidebar.
The most obvious implementation works:
App.TweetsIndexRoute = Em.Route.extend({
model: function(params) {
var tweet = App.Tweet.fetch(params.id),
suggestions = App.Suggestions.fetch(params.id);
return RSVP.all(tweet, suggestions);
}
});
The route makes the two fetches in parallel and then blocks on both. Everything works well.
Then your users start complaining. The /api/suggestions/292
requests take a long time, and they’re blocking the users from seeing the main content they want to see. So you decide to fetch them later:
App.TweetsIndexRoute = Em.Route.extend({
model: function(params) {
return App.Tweet.find(params.id);
},
setupController: function(controller, tweet) {
this._super(controller, tweet);
controller.set('suggested', App.Suggested.find(tweet.get('id'));
}
});
But now your app starts spitting out error messages about the sidebar view re-rendering while it’s in the inBuffer
state (since the AJAX call can come back any time). To get around that, you delay the fetch until after the first render:
setupController: function(controller, tweet) {
this._super(controller, tweet);
Em.run.scheduleOnce('afterRender', function() {
controller.set('suggested', App.Suggested.find(tweet.get('id'));
});
}
Is that the best practice? Is there somewhere else these ancillary models should be fetched and connected?