Re: Ambient light API redesign

On Fri, Sep 5, 2014 at 4:18 PM, Tim Volodine <timvolodine@google.com> wrote:

> So how about something like this:
> (taking Device Orientation API as example)
>
> enum SamplingFrequencyType {
>  "low",
>  "normal",
>  "high"
> };
>
> partial interface Navigator {
>  Promise<DeviceOrientationSensor>
> getDeviceOrientationSensor(SamplingFrequencyType);
> };
>
> interface Sensor : EventTarget {
>  readonly attribute double samplingFrequency;
>  attribute EventHandler onchange;
> };
>
> interface DeviceOrientationSensor : Sensor {
>  readonly attribute OrientationData currentOrientation;
>  DOMMatrix getCurrentOrientationAsRotationMatrix();  // by means of example
> };
>
>
> Example 1:
>
> function sensorSuccess(sensor) {
>  console.log(sensor.currentOrientation);
>  sensorManager.addEventListener(‘change’, function() {
>      console.log(this.currentOrientation);
>  });
> }
>
> function sensorFailed() {
>  console.log(“failed to obtain orientation sensor”);
> }
>
> navigator.getDeviceOrientationSensor(“high”).then(sensorSuccess,
> sensorFailed);
>
>
> Example 2 (using requestAnimationFrame):
>
> var sensor = null;
> function updateFrame() {
>   window.requestAnimationFrame(updateFrame);
>   if (sensor)
>     console.log(sensor.currentOrientation);
>   // do something else
> }
>
> navigator.getDeviceOrientationSensor(“high”).then(
>   function(orientationSensor){ sensor = orientationSensor; },
>   function() { console.log("error"); });
>
> window.requestAnimationFrame(updateFrame);
>
>
I've been experimenting with alternative APIs for Device Orientation and
the API design has converged naturally on the pattern described above. This
library is available at [1].

Having a Promise-based API means we can initialise and resolve a Promise
object to a Device Orientation object only if/when the platform pipeline
has been set up and has delivered its first device orientation sensor data.
If any part of that pipeline set up fails then we have a way to reject the
Promise object with timeout/not-implemented/permission-denied errors as
appropriate. Having that mechanism to throw errors on set up allows web
developers to take any necessary fallback action in their web apps such as
to provide manual mouse/touch/keyboard controls instead of relying on
unsupported Device Orientation events.

Simultaneously, the 'DeviceOrientationSensor' interface above (called
'FULLTILT.DeviceOrientation' in [1]) is also exposed to web apps and is
furnished with a constructor. Web developers can thus create new
DeviceOrientationSensor objects (or AmbientLightSensor objects, etc)
directly via that interface's constructor, bypassing the Promise-based
mechanism for object invocation.

Creating a new 'DeviceOrientationSensor' object via its interface's
constructor does not automatically imply that the current browser will
deliver deviceorientation events (see: 'window.DeviceOrientationEvent'
being exposed on multiple platforms but those platforms not delivering
device orientation events [2]). Using this approach does, however, allow
you to use the API in the way Rick is proposing.

In summary, using Promises to create new sensor objects provides a natural
feature detection mechanism, allows the UA to set up the platform pipeline
for delivering hardware sensor events asynchronously, allows the UA
implement timeouts, error conditions on that pipeline set up and, reject
Promises in case any error condition is met in that set up process. It
avoids the 'warm up' phase of hardware sensor data delivery (where sensor
data has not yet been received at the UA and is thus 'null' when sensor
change events are fired prematurely toward web apps) though that can be
overridden by invoking the object directly via its constructor.

My Device Orientation library based on the pattern above is available at
[1].

- Rich

[1] https://github.com/richtr/Full-Tilt

[2] https://github.com/w3c/deviceorientation/pull/12

Received on Tuesday, 14 October 2014 09:42:02 UTC