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

On Thu, May 6, 2010 at 9:23 PM, ben turner <bent.mozilla@gmail.com> 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;
>  };
>
> 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);
>  };
>
> >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.
>
> So, what do you guys think?
>

This looks great!

The only thing I think we need to change is the name "source".  It's just
not very clear/descriptive.  What about "requestor" or "parent"?  Or maybe
there's another name that's even more clear?

J

Received on Monday, 10 May 2010 12:24:44 UTC