Re: [IndexedDB] Changes to IDBRequest and specification of the success and error events

Hi Ben,

On May 6, 2010, at 1:23 PM, ben turner wrote:

> Hi folks,
> 
> We've been playing around with the async API and have made some
> changes to the IDBRequest interface that we'd like feedback on and
> hopefully inclusion in the spec. Here's what we have now:
> 
>  interface IDBRequest : EventTarget {
>    void abort();
> 
>    const unsigned short INITIAL = 0;
>    const unsigned short LOADING = 1;
>    const unsigned short DONE = 2;
>    readonly attribute unsigned short readyState;
> 
>    attribute Function onsuccess;
> 
>    attribute Function onerror;
>  };
> 
>  interface IDBEvent : Event {
>    readonly attribute Any source;
>  };
> 
>  interface IDBSuccessEvent : IDBEvent {
>    readonly attribute Any result;
>  };
> 
>  interface IDBErrorEvent : IDBEvent {
>    readonly attribute unsigned short code;
> 
>    readonly attribute DOMString message;
>  };
> 

I like it so far.

> First, the obvious stuff. We've moved the error and result property
> from the request to their respective events. Having everything on the
> event makes it much easier to write callback functions, in my opinion.
> Example in a sec. We've also made the success and error event keep a
> source property that can be used to get back to the object that
> generated the request. This may be a bit confusing but the example
> will help. Here we go:
> 
> The following code uses the old API to put two values into an object
> store and then alert the two keys that were created. We're assuming
> that the object store "Data" exists and is an autoIncrementing store.
> 
>  var request = indexedDB.open("MyDB", "My Cool Database");
>  request.onsuccess = function(event) {
>    // request.result is an IDBDatabaseRequest
>    var request2 = request.result.openObjectStore("Data");
>    request2.onsuccess = function(event) {
>      // request2.result is an IDBObjectStoreRequest
>      var objectStore = request2.result;
>      var request3 = objectStore.put("foo");
>      request3.onsuccess = function(event) {
>        // request3.result is a key value
>        var key1 = request3.result;
>        var request4 = objectStore.put("bar");
>        request4.onsuccess = function(event) {
>          // request4.result is a key value
>          var key2 = request4.result;
>          alert("All done, keys are " + key1 + " and " + key2);
>        };
>        request4.onerror = function(event) {
>          alert(request4.error.message);
>        };
>      };
>      request3.onerror = function(event) {
>        alert(request3.error.message);
>      };
>    };
>    request2.onerror = function(event) {
>      alert(request2.error.message);
>    };
>  };
>  request.onerror = function(event) {
>    alert(request.error.message);
>  };

The sequencing of calls doesn't change regardless of the changes you propose.

> 
>> From that sample you can see that the error functions are almost
> identical but they have to keep track of the proper request that
> created them in order to get the right error message.
> 
> The success functions also have to keep track of the request that
> created them to know what the result property contains. Note also that
> we have to save objectStore in request2.onsuccess in order to do an
> additional put into the object store in request3.onsuccess. Keeping
> track of all of this is really tedious and error prone.
> 
> With the changes outlined above, this code can be condensed to the following:
> 
>  function errorHandler(event) {
>    // event.source is different each time here but can be used to
> figure out which operation failed
>    // event.code holds the error code
>    alert(event.message);
>  }
>  var request = indexedDB.open("MyDB", "My Cool Database");
>  request.onerror = errorHandler;
>  request.onsuccess = function(event) {
>    // event.source is an IndexedDatabaseRequest
>    // event.result is an IDBDatabaseRequest
>    request = event.result.openObjectStore("Data");
>    request.onerror = errorHandler;
>    request.onsuccess = function(event) {
>      // event.source is an IDBDatabaseRequest
>      // event.result is an IDBObjectStoreRequest
>      request = event.result.put("foo");
>      request.onerror = errorHandler;
>      request.onsuccess = function(event) {
>        // event.source is an IDBObjectStoreRequest
>        // event.result is a key value
>        var key1 = event.result;
>        request = event.source.put("bar");
>        request.onerror = errorHandler;
>        request.onsuccess = function(event) {
>          // event.source is an IDBObjectStoreRequest
>          // event.result is a key value
>          var key2 = event.result;
>          alert("All done, keys are " + key1 + " and " + key2);
>        };
>      };
>    };
>  };
> 
> We haven't done much to compress the length of the script here, but
> you'll notice that each success handler is relatively self contained
> and doesn't really need to use closures to perform further operations.
> There's also no need to remember keep track of whether or not you want
> request3 or request2 or request5000. The error handler is much easier
> to reuse as well.

I am not sure that each request would have to be kept accessible. That part of the first code listing doesn't make sense to me. However, I am all for this improvement in the spec.

> 
> So, what do you guys think?

Please note though that while this improves the usability of the async API, there is still a lot to be desired.

Received on Tuesday, 11 May 2010 20:00:42 UTC