How to synchronize multiple Backbone.js fetches?

2019-01-31 17:35发布

I’m a bit new to Backbone.js, but am already impressed by everything it can do for me, and am trying to learn the patterns and best practices now.

I have two collections:

var CollA = Backbone.Collection.extend({
    model: ModelA,
    url: '/urlA'
});

var CollB = Backbone.Collection.extend({
    model: ModelB,
    url: '/urlB'
});

var collA = new CollA;
var collB = new CollB;

When loading my app, I need to fetch both of these collections from the server, and run some bootstrap code when it’s guaranteed that both fetches have completed.

Here’s how I did it for now:

collA.fetch({success: function() {
    collB.fetch({success: function() {
        // run the needed code here.
    }});
}});

This works, the needed code is guaranteed to run only after both fetches complete successfully. It is clearly inefficient though, because the fetches run serially, one after another.

What would be a better pattern to do this, to run the fetches in parallel and then run some code once both fetches have completed successfully?

3条回答
小情绪 Triste *
2楼-- · 2019-01-31 17:52

I like @JayC's answer if you have to fetch each collection individually. You could argue that a single fetch to the server would be better as opposed to multiple fetches. If you are fetching this data on application load, I would do a single call to the server and then pass the data to your relevant collections. It truly depends on how many collections you have to fetch on application load, but I honestly prefer making one call to the server then passing the data to my relevant collections.

$.ajax({
    url: "path/to/app-load-data"
}).done(function(data) { 
    collA = new CollA(data.collA);
    collB = new CollB(data.collB);
});

This obviously will depend if you can manipulate your api and the above does not follow REST. But then again you are making one call to the server as opposed to multiple calls.

查看更多
走好不送
3楼-- · 2019-01-31 17:56

If you're using jQuery, use when:

$.when(collA.fetch(),collB.fetch()).done(function(){
    //success code here.
});

Background:

You pass in one or more deferreds to $.when. It so happens that the "jqXHR" that collections return implements the promise/Deferred interface that can be combined into a new promise using $.when. The requests will essentially be concurrent (well, as much as javascript allows) and the function passed to .done will execute only when both fetches are successful.

查看更多
够拽才男人
4楼-- · 2019-01-31 18:00

As @JayC said you could use $.when from jQuery, other option that I prefer is the after function (from Underscore), which execute one time just after expected calls are completed.

http://underscorejs.org/#after

function runMyApp(){
  // run the needed code here.
  console.log('This will run one time but until both fetch are being completed.');
}

//2 because you have two collections
var renderApp = _.after(2, runMyApp);
collA.fetch({success: renderApp});
collB.fetch({success: renderApp});
查看更多
登录 后发表回答