Use of Deferreds and Promises with Adventure.js for HTML5 Video Popcorn.js SDK
/**
* Below is excerpted code that was improved to properly use Deferreds, construction, and $.when()
*
* @see https://github.com/rwldrn/adventure/blob/master/src/adventure.js
**/
init: function( options ) {
// Program references
var
// Shorthand pointer back to Adventure object.
self = Adventure,
// Initialize a popcorn instance by passing the
// specified media element's ID to Popcorn()
self.pop = Popcorn( options.mediaId );
// Localize the options.scenarios data property
self.scenarios = options.scenarios;
// Create two promises
loadQueue = [
// Load the video will resolve when video is playable
$.Deferred( function(dfd){
// Listen for the custom "canplayall" event hook
// to be triggered. Similar to "canplaythrough",
// the "canplayall" event fires when the video fires
// "canplaythrough" for the _first_ _time_ _only_
self.pop.listen( "canplayall", function() {
dfd.resolve( self.pop );
});
}).promise(),
// when events have been loaded in from the specified file
$.Deferred( function(dfd){
// Make a request for the track event data in the
// specified file stored on the server
$.getJSON( options.events, function( data ) {
dfd.resolve( data );
});
}).promise()
];
// When both deferred objects have been resolved,
// proceed to setting up the video's track events,
// and cues
$.when.apply( null, loadQueue )
.done( function( media, events ) {
console.log( "Continue to movie setup", media, events );
var
// Map an object of data properties to setup tasks
// Create new setup completion deferreds for each
datas = {
cues : options.cues || {},
tracks : events || [],
handlers: options.handlers
},
queue = [ ];
// Iterate setup tasks and call each with correlated data
_.forEach( self.setup, function( fn, key ) {
queue.push( $.Deferred( function(dfd){
// Call setup function
// Set context to Popcorn instance
// Pass correlated data as argument
fn.call( media, datas[ key ], dfd, self );
// If the expected setup data is actually empty,
// we can premptively resolve the setup completion deferred
if ( _.size( data ) === 0 ) {
dfd.resolve();
}
}).promise());
});
// When all setup deferreds are resolved,
// Setup is complete, can run tests or play game
$.when.apply( null, queue )
.then( function() {
// Setup is complete
console.log( "Ready for assertion tests" );
self.pop.play();
deferreds = [ ];
});
});
},