chrisguttandin / timing-object

An implementation of the timing object specification.
MIT License
37 stars 1 forks source link

Differentiating between self call and external call #229

Open infojunkie opened 1 month ago

infojunkie commented 1 month ago

I am working on a media player that uses a TimingObject using your implementation here, and I have a question about the expected programming model. Consider the following cases:

But how can the player differentiate between internal change events (as caused by play() invocations) versus external changes (such as update({ velocity }) ? Is the TimingObject programming model expecting both scenarios, or is it implied that ALL player changes should be done via TimingObject.update() calls?

PS. I've tried wrapping the player's calls to this._timingObject.update() within a function that unregisters its own change listener before the call, and re-registers it after the promise resolves, but it would seem that the change event is generated outside of the TimingObject.update() calls completely.

chrisguttandin commented 1 month ago

The 'change' event gets dispatched in a setTimeout() call.

https://github.com/chrisguttandin/timing-object/blob/5220f945ebaf64978bde6a5dfe79718dbe5dc738/src/factories/timing-object-constructor.ts#L296

I think the following should work:

timingObject.removeEventListener('change', yourChangeListener);
timingObject.update({ velocity: 2 });
setTimeout(() => timingObject.addEventListener('change', yourChangeListener));

But maybe it's a bit more robust to do something like this:

let invocationToSkip = 0;

timingObject.addEventListener('change', () => {
    if (invocationToSkip > 0) {
        invocationToSkip -= 1;
    } else {
        yourChangeListener();
    }
});

// ... and later on ...
skipNextInvocation += 1;
timingObject.update({ velocity: 2 });

Would that work for you?

infojunkie commented 1 month ago

Thanks @chrisguttandin for your reply. Regarding the more robust version: is it really the removeEventListener() call that does the processing that you mention? I would have expected addEventListener.

chrisguttandin commented 1 month ago

Oh, sorry for that. You're right. I fixed the typo in the comment above.

infojunkie commented 1 month ago

Thanks for your help here. I am not sure that counting the skippable invocations would work, for example in case there happens to be interleaving internal and external calls. In my opinion, allowing the timing vector update to carry an additional, arbitrary payload that the event listener interprets would solve the problem definitively and without concurrency issues.

But at a higher level, I still am not clear on whether the Timing Object programming model accounts for the difference between these 2 cases - or if I am misunderstanding something fundamental.