Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to wait to invoke callback until multiple backbone collection have synced?

I'd like to run view.render() if both collectionA and collectionB have fired 'sync' event. Something like this.

collectionA = new CollectionA();
collectionB = new CollectionB();

view.listenTo([collectionA, collectionB], 'sync', view.render);

collectionA.fetch(); // do not call view.render yet.
collectionB.fetch(): // call view.render after fetch.

I know there is a way to use $.when() or _.after() like this answers. How to synchronize multiple Backbone.js fetches?

But I think these are not event-driven way. Is there any event-driven way on Backbone.js?

like image 764
kkpn Avatar asked Apr 16 '13 09:04

kkpn


1 Answers

You can use a combination of underscore's after method to only execute the callback when it's been called a number of times, and Backbone.Events.once to ensure that you don't trigger the handler prematurely, if one of the collections fires two sync events, instead of one from each:

var callback = _.after(2, view.render);
collectionA.once('sync', callback, view);
collectionB.once('sync', callback, view);

Or you can wrap the logic into a utility function, so you can use it with a variable number of event sources:

function onceAll(eventSources, eventName, handler, context) {
  handler = _.after(eventSources.length, handler);
  context = context || this;
  _.each(eventSources, function(source) {
      source.once(eventName, handler, context);
  });
}

Usage:

onceAll([collectionA, collectionB], 'sync', view.render, view);

/Code samples not tested.

like image 192
jevakallio Avatar answered Nov 05 '22 21:11

jevakallio