Providing a view after several asynchronous ajax calls using Backbone

I have a spine and I want to display the html AFTER 2 asynchronous calls:

initialize: function (model, options) { team.fetch({ success: function (collection) { //do some things }); goal.fetch({ success: function (collection) { //do some things }); this.render(); } render: function () { this.$el.html(template()); return this; } 

Obviously with the above code, the html template will be returned before / during ajax calls. Usually when one ajax call, I do:

 initialize: function (model, options) { var that = this; team.fetch({ success: function (collection) { //do some things that.render(); }); } render: function () { this.$el.html(template()); return this; } 

What is the most elegant way to do this with a few ajax calls?

+4
source share
2 answers

I would use jQuery Deferred , in particular $.when . This allows you to perform an action only if several asynchronous operations are completed. Use it like this:

 var ajax1 = team.fetch({ ... }); var ajax2 = goal.fetch({ ... }); $.when( ajax1, ajax2 ).done( this.render ); 

Edit

As @muistooshort points out, you also need to bind render so that it is called with the correct context (otherwise this inside render will refer to an ajax object instead of a view object):

 _.bind(this.render, this); 
+3
source

Just so you can appreciate what JQuery Deferred is getting rid of, this is an example of how you could solve this very common problem without it. (Imagine the same code for 4 collections / models, not just 2.)

 initialize: function(model, options) { team.fetch(); goal.fetch(); this.listenTo(team, 'sync', this.teamFetched); this.listenTo(goal, 'sync', this.goalFetched); }, teamFetched: function() { this._teamFetched = true; // if goal also fetched, call & return this.render() return (( this._goalFetched ) ? this.render() : this); }, goalFetched: function() { this._goalFetched = true; // if team also fetched, call & return this.render() return (( this._teamFetched ) ? this.render() : this); } render: function() { this._goalFetched = this._teamFetched = false; this.$el.html(template()); return this; } 
+1
source

All Articles