W3C home > Mailing lists > Public > public-webapps@w3.org > July to September 2010

Re: [IndexedDB] Re: onsuccess callback in race condition?

From: Jeremy Orlow <jorlow@chromium.org>
Date: Thu, 15 Jul 2010 18:13:28 +0100
Message-ID: <AANLkTikMsb6FfBO2wHarFgDOMBW5-d2X5nQlwAajMxiE@mail.gmail.com>
To: victor.hong@nokia.com
Cc: public-webapps@w3.org
On Thu, Jul 15, 2010 at 6:04 PM, <victor.hong@nokia.com> wrote:

>
> Hi Jeremy,
>
> Thank you for responding. If I understand you correctly, the example 1
> could produce a race condition,
>

I don't see how.  onsuccess is always set immediately after the request
object is created by the asynchronous call.


> and example 2 will not.
>

This example is completely outdated and will not work period.  Please take a
look at the latest editors draft.  (A lot of the async changes were just
committed.)


> However, example 2 will assume that request object is a member of IndexDB,
> which seems not in the interface for the time being:
> interface IDBFactory {
>
>    readonly attribute DOMStringList databases;
>     IDBRequest open (in DOMString name, in DOMString description) raises
> (IDBDatabaseException);
> };
>
> Should request be part of every indexedDB object?
>
> Regarding to allowing someone to set an onsuccess/onerror handler after the
> event has fired, I think that itís very convenient.
>

Are you saying _not_ allowing it is convenient?  I'm going to assume so
because there's really no use case for why one would want to set them after
they would have fired.


> One possible idea, is to offer an addCallback function in request object.
> So it will be like;
>
> var request = IndexedDB.open();
> request.addOnSuccessCallback(mySuccessCallback);
> request.addOnErrorCallback(myErrorCallback);
>
> The addOnSuccessCallback call will
>
>    1. make assignment request.onsuccess =  mySuccessCallback;
>    2. check the ready state, if the open() call has been fired, and
>    completed, then call mySuccessCallback(event) immediately with event object
>
>
> Could this work?
>

Well, most of this is already done since IDBRequest is an event target, so
you can do .addEventListener.  As for firing afterwards, I don't believe
there's any precident in any other event listener.  And I can't think of too
many cases where you'd really need to set the event handler after doing some
other asynchronous action, so I don't think it's worth creating our own
custom behavior for this case.


>
> If we take this approach, the request object does not need to be part of
> IndexedDB object. It will be returned from indexedDB.open() then callbacks
> can be added to it, without worrying about race condition.
>

There aren't race conditions currently.  You just need to set it before you
return control to the browser.


>
> Victor
>
>
> On 7/15/10 12:14 PM, "ext Jeremy Orlow" <jorlow@chromium.org> wrote:
>
> First of all, any chance you could prefix IndexedDB discussions with
> [IndexedDB] in the subject so that people have the option to filter them if
> they wish?
>
> To answer your question:  The intention is that onsuccess is not inspected
> until the event would fire.  And the event would not fire until after you
> return from your currently running JavaScript.  But if you did do something
> asynchornous and then set it after that, it would be a race.  But you could
> look at the ready state to see whether you've missed the boat or not.
>
> This does bring up an interesting question.  Should we allow someone to set
> an onsuccess/onerror handler after the event has fired?  Afte rall, we know
> there's no chance of it ever firing.
>
> Also, I wonder if we should try to add some text to make this more clear in
> the spec.
>
> J
>
> On Thu, Jul 15, 2010 at 4:13 PM,  <victor.hong@nokia.com> wrote:
>
> Hi,
>
> I would like to get some clarification on async implementation of the
> indexedDB API.
>
> Example 1:
> Below is a sample code from the following blog article.
> http://hacks.mozilla.org/2010/06/comparing-indexeddb-and-webdatabase/
>
> var request = window.indexedDB.open("CandyDB",
>                                     "My candy store database");
> request.onsuccess = function(event) {
>   var db = event.result;
>   if (db.version != "1") {
>     // User's first visit, initialize database.
>     var createdObjectStoreCount = 0;
>     var objectStores = [
>       { name: "kids", keyPath: "id", autoIncrement: true },
>       { name: "candy", keyPath: "id", autoIncrement: true },
>       { name: "candySales", keyPath: "", autoIncrement: true }
>     ];
>
>     function objectStoreCreated(event) {
>       if (++createdObjectStoreCount == objectStores.length) {
>         db.setVersion("1").onsuccess = function(event) {
>           loadData(db);
>         };
>       }
>     }
>
>     for (var index = 0; index < objectStores.length; index++) {
>       var params = objectStores[index];
>       request = db.createObjectStore(params.name <http://params.name> ,
> params.keyPath,
>
>                                      params.autoIncrement);
>       request.onsuccess = objectStoreCreated;
>     }
>   }
>   else {
>     // User has been here before, no initialization required.
>     loadData(db);
>   }
> };
>
> In this code, request is returned from request = window.indexedDB.open()
> call, then request.onsuccess = function() {...} is assigned.
>
> Maybe I don't fully understand how this IndexedDB works,
> it seems that there could be a race condition between the open() operation
> and request.onsuccess assignment. The open() operation could be completed
> before request.onsuccess got assigned to a callback function. Does this
> mean
> that the request.onsuccess callback function will not be called?
>
> Is there a mechanism to assure that the callback gets called regardless
> whether the open() operation completed or not when request.onsuccess is
> assigned to a callback function?
>
> Of course, the same issue exists for all other async calls.
>
> Whether this can be assured or not, maybe the spec document can point it
> out
> if not already in the coming draft.
>
> Example 2:
> On the other hand, in the July 15, 2010 editor's draft, 3.2.2 The
> IDBRequest
> Interface section, there is an example:
>
> indexedDB.request.onsuccess = function(evt) {...};
> indexedDB.request.onerror = function(evt) {...};
> indexedDB.open('AddressBook', 'Address Book');
>
> This indicates that request object is a member of indexedDB interface, and
> request.onsuccess can be assigned to a callback before indexDB.open() is
> called, therefore is no race condition issue here.
>
> But IndexDB is a
> interface IDBFactory {
>     readonly attribute DOMStringList databases;
>     IDBRequest open (in DOMString name, in DOMString description) raises
> (IDBDatabaseException);
> };
>
> It does not appear to have a request object as member.
>
>
> Can someone clarify these above 2 examples for me?
>
> Does request.onsuccess need to be assigned to a callback before
> indexDB.open() get called to avoid race condition? Like in example 2)
>
> Maybe both examples are correct. Then what makes sure that in example 1)
> the
> callback function get called even if open() has been completed before the
> callback function is assigned to request.onsuccess?
>
> Thank you.
> Victor
>
>
>
>
>
>
Received on Thursday, 15 July 2010 17:14:20 GMT

This archive was generated by hypermail 2.3.1 : Tuesday, 26 March 2013 18:49:39 GMT