Plyr: [3.0.0-beta.15] Events being emitted, but callbacks not firing.

Created on 27 Feb 2018  路  8Comments  路  Source: sampotts/plyr

I'm attempting to hook into the ready event using:

import plyr from 'plyr';

const player = new plyr(el, {...});

player.on('ready', e => {...});

With debugging enabled, you can see the event: ready line emitted in the console, but the callback passed to instance.on(...) never fires. There seems to be a bit of a disconnect here.

Any idea why this might be happening?

All 8 comments

I fixed this problem by changing the following in ui.js on line 87:

// Ready event at end of execution stack
utils.dispatchEvent.call(this, this.media, 'ready');

With the following:

// Ready event at end of execution stack
// Set a small delay or out on ready event attached to the plyr instance is not triggered
setTimeout(() => {
      utils.dispatchEvent.call(this, this.media, 'ready');
}, 50);

So basically listening for the ready right after creating the plyr instance will fail, as the ready event can fire sooner, so definitely a disconnect as you were saying. Not sure how to make a more a more elegant solution to fit with the plyr codebase.

Is it perhaps worth making the ready event a listener, similar to the listeners available for the controls? That way we can define our callback as part of the supplied options and this race condition might be avoided.

Fixed timeouts doesn't guarantee solving race conditions, just reduces their odds, and may break again in the next browser upgrade or even other current browsers.

@r3oath's solution is better imo. But the API is less nice.

Alternatively on could perhaps check isReady() before actually adding the ready listener event and instead trigger instantly when this is the case. Since js is single threaded I believe this is safe as long as the event listener is added in the same "tick".

I think in this case maybe using a 0 setTimeout would work as it would execute "async" at the end of the current execution stack wouldn't it? That's how I've always remembered a zero timeout to work. It does seem to fix it in this instance anyway...

window.setTimeout(() => {
    utils.dispatchEvent.call(this, this.media, 'ready');
}, 0);

I've used the above to solve it for now in v3.0.0-beta.16. Not ideal I know but unless we can come up with something better, it'll work for now. I can always add the callback too but I've never really been a fan of those callbacks in the options anyway. I'd rather any external code used events and then preventDefault if the default behaviour wasn't desired.

馃憤 I'm not sure my terminology is correct, but setTimeout with 0 duration will run the method on the next "tick" (next iteration in the eventloop), so yes. I probably over thought it by assuming ready should work retroactively, like jquery etc.

In retrospect I think your solution is better (less code & more consistent).

And sorry @gehaktmolen. If you would have made that timeout 0 it would been the same solution.

All good 馃憤

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Lycanthrope picture Lycanthrope  路  4Comments

Antonio-Laguna picture Antonio-Laguna  路  3Comments

Generalomosco picture Generalomosco  路  3Comments

TheZoker picture TheZoker  路  4Comments

osamay picture osamay  路  4Comments