Specifying the association with an online timing service

Hi again,

Looking at the TimingObject interface as defined in the spec [1], I'm 
wondering what would be the proper way to associate a TimingObject 
instance with an online timing service and to start using it.

The spec currently currently defines an under-specified "src" attribute 
but I'm wondering whether it's of any use in the end: using a URL would 
probably require that we define a custom URL scheme to tell the user 
agent about the protocol to use. Since we want to leave some freedom for 
online timing services to define their own mechanisms, that does not 
seem to be a good approach and I would just drop it for now.

I explored the possibility to use an "srcObject" attribute to associate 
a local instance with a TimingProvider instance connected to an online 
timing service in my prototype [2]. However, this means that, before 
being able to use the timing object, the code needs to listen to the 
"readystatechange" event, which is somewhat tedious.

Also, "srcObject" could be re-assigned at any time, so the code needs to 
take that possibility into account.

var runWhenReady = function () { [[...]] };
var provider = [[get timing provider instance]];

var alreadyRun = false;
var timing = new TimingObject();
timing.srcObject = provider;
timing.onreadystatechange = function (evt) {
   if (!alreadyRun && (evt.value === 'open')) {
     alreadyRun = true;
     run();
   }
};

To simplify the life of developers, it might be better to define a 
dedicated "open" event (as in the WebSockets API) instead of a 
"readystatechange" event and, assuming the TimingProvider has a simple 
(connecting, open, closing, closed) lifecycle, to prevent the timing 
object from being associated with more than one TimingProvider, e.g. by 
dropping the srcObject attribute and rather passing the TimingProvider 
instance as part of the constructor, as in:

var timing = new TimingObject(provider);
timing.onopen = runWhenReady;

Perhaps more fashionable, there could be a ready() method that returns a 
Promise that resolves when the association is ready and rejects when 
connection goes wrong:

var timing = new TimingObject(provider);
timing.ready().then(runWhenReady);

... but I think I still prefer the "onopen" mechanism. Any thought?


The "TimingProvider" interface would also need to be specified. In the 
end, all I needed was something pretty close to the TimingObject interface:

interface TimingProvider : EventTarget {
   readonly attribute DOMString readyState;
   readonly attribute StateVector vector;
   readonly attribute Interval range;
   attribute EventHandler onreadystatechange;
   StateVector query();
   void update(StateVector newVector);
   void close();
}

I'm not entirely convinced that the "vector" attribute needs to be 
exposed in practice but that's a minor detail.


The interface is so close to TimingObject that it begs the question as 
to whether a timing object associated with an online timing service 
should not be seen as a derived TimingObject class rather than as a 
TimingObject associated with a TimingProvider. The only real difference 
is the "timeupdate" event (and a few helper methods that could also be 
added to a TimingProvider). I guess it makes sense to keep a distinction 
if user agents implement the TimingObject interface natively whereas 
TimingProvider classes may be defined in regular JS libraries.

Should I sketch some text along these lines for the TimingProvider 
interface?

Francois.


[1] http://webtiming.github.io/timingobject/
[2] https://github.com/tidoust/timingservice

Received on Monday, 8 June 2015 15:18:50 UTC