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

[IndexedDB] Re: onsuccess callback in race condition?

From: <victor.hong@nokia.com>
Date: Thu, 15 Jul 2010 19:04:21 +0200
To: <jorlow@chromium.org>
CC: <public-webapps@w3.org>
Message-ID: <C864B7D5.D7DD%victor.hong@nokia.com>

Hi Jeremy,

Thank you for responding. If I understand you correctly, the example 1 could produce a race condition, and example 2 will not.

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.

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?

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.

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:05:10 GMT

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