toxicate20
toxicate20

Reputation: 5410

Backbone foreach waiting

I've got a track model and a collection of tracks. The model itself has a function play() that plays a single track. The collection should be able to play each track after another when the single track (in order of the list) is finished.

Model:

app.Track = Backbone.Model.extend({
    defaults: {...},
    initialize: {...},
    play: function(playlist) {
       if(finished && playlist) {
           Backbone.pubSub.trigger('finishedPlaybackLoadNext')
       } else {
           Backbone.pubSub.trigger('finishedPlayback')  
       }
    },
})

Collection:

var TrackList = Backbone.Collection.extend({
    model: app.Track,
    nextOrder: function() {...},
    comparator: function( track ) {...},
    playAll: function() {
       this.models.forEach(function(item) {
          item.play(true); //true = play as playlist
       });
    }
})

As expected the forEach does not wait till play is done for each individual model in the list. How can I achieve this kind of waiting?

Edit: I am using a global trigger/subscriber for events to share them within different views.

Backbone.pubSub = _.extend({}, Backbone.Events);

Upvotes: 0

Views: 354

Answers (1)

sra
sra

Reputation: 6418

I think you should have two models for the purpose of playing songs in a row. First you have a Track model and its corresponding TrackList collection, but then you would have another model called PlayList and a collection for that too.

The Track's play function should then take another parameter which would be a callback that has to be executed when the Track has finished playing. in this way you could have a play function on a PlayList too and this function would take care of playing all songs in a row through nested callbacks (sounds like recursive fun :P).

edit: I went ahead and hacked some small implementation of what I was thinking of. I'm not using Backbone here, but i'm sure you could adapt the idea, if you have some waz of passing a callback function to the Songs play function (by the way... how are you actually playing your songs?).

Song = function(name) {
  var play = function() {
    console.log(name);
    sleep(1000);
  };

  this.name = name;
  this.play = function(cb) {
    play();
    if (typeof cb == "function") {
      cb.call(this);
    }
  };
};

PlayList = function(songs) {
  this.play = function(cb) {
    // define a function that calls the first song with a callback 
    // that calls the next song with a callback that calls the next
    // ... untill the last songs play function gets called with cb 
    // (parameter top this function) as the callback.
    var playFirstSong = _.reduce(songs.reverse(), function(cb, song) { 
      return function() {
        song.play(cb);
      };
    }, cb);

    playFirstSong();
  };
};

I made a jsFiddle out of this too.

Upvotes: 1

Related Questions