- From: Francois Daoust <fd@w3.org>
- Date: Mon, 08 Jun 2015 17:18:37 +0200
- To: public-webtiming@w3.org
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