Skip to content

Commit

Permalink
Added a synchronous option to component.ready
Browse files Browse the repository at this point in the history
For 5.0 we switched ready() to always execute listeners
asynchronously, but for most internal use cases we would
prefer the ready function to execute immediately if the
component is already ready.

Fixes videojs#2326
Related: videojs#2382, videojs#1667, videojs#2188
  • Loading branch information
heff committed Jul 22, 2015
1 parent 8be7810 commit f087b51
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 17 deletions.
17 changes: 11 additions & 6 deletions src/js/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -585,7 +585,7 @@ class Component {
* @param {String|Component} first The event type or other component
* @param {Function|String} second The event handler or event type
* @param {Function} third The event handler
* @return {Component}
* @return {Component}
* @method on
*/
on(first, second, third) {
Expand Down Expand Up @@ -745,14 +745,19 @@ class Component {
* it will trigger the function immediately.
*
* @param {Function} fn Ready listener
* @param {Boolean} sync Exec the listener synchronously if component is ready
* @return {Component}
* @method ready
*/
ready(fn) {
ready(fn, sync=false) {
if (fn) {
if (this.isReady_) {
// Ensure function is always called asynchronously
this.setTimeout(fn, 1);
if (sync) {
fn.call(this);
} else {
// Call the function asynchronously by default for consistency
this.setTimeout(fn, 1);
}
} else {
this.readyQueue_ = this.readyQueue_ || [];
this.readyQueue_.push(fn);
Expand Down Expand Up @@ -1208,7 +1213,7 @@ class Component {
* Registers a component
*
* @param {String} name Name of the component to register
* @param {Object} comp The component to register
* @param {Object} comp The component to register
* @static
* @method registerComponent
*/
Expand Down Expand Up @@ -1244,7 +1249,7 @@ class Component {
* Sets up the constructor using the supplied init method
* or uses the init of the parent object
*
* @param {Object} props An object of properties
* @param {Object} props An object of properties
* @static
* @method extend
*/
Expand Down
39 changes: 28 additions & 11 deletions test/unit/component.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -365,26 +365,43 @@ test('should add listeners to other components that are fired once', function(){
});

test('should trigger a listener when ready', function(){
expect(2);
let initListenerFired;
let methodListenerFired;
let syncListenerFired;

var optionsReadyListener = function(){
ok(true, 'options listener fired');
};
var methodReadyListener = function(){
ok(true, 'ready method listener fired');
};
let comp = new Component(getFakePlayer(), {}, function(){
initListenerFired = true;
});

var comp = new Component(getFakePlayer(), {}, optionsReadyListener);
comp.ready(function(){
methodListenerFired = true;
});

comp.triggerReady();
this.clock.tick(1);

comp.ready(methodReadyListener);
comp.ready(function(){
syncListenerFired = true;
}, true);

ok(!initListenerFired, 'init listener should NOT fire synchronously');
ok(!methodListenerFired, 'method listener should NOT fire synchronously');
ok(syncListenerFired, 'sync listener SHOULD fire synchronously if after ready');

this.clock.tick(1);
ok(initListenerFired, 'init listener should fire asynchronously');
ok(methodListenerFired, 'method listener should fire asynchronously');

// Listeners should only be fired once and then removed
initListenerFired = false;
methodListenerFired = false;
syncListenerFired = false;

// First two listeners should only be fired once and then removed
comp.triggerReady();
this.clock.tick(1);

ok(!initListenerFired, 'init listener should be removed');
ok(!methodListenerFired, 'method listener should be removed');
ok(!syncListenerFired, 'sync listener should be removed');
});

test('should add and remove a CSS class', function(){
Expand Down

0 comments on commit f087b51

Please sign in to comment.