Issues with IndexedDB and Chrome

This post is more than 2 years old.

I've been doing some investigation into IndexedDB lately, and one of the issues I ran into was Chrome not following the spec correctly. As a blogger I have the luxury of simply not caring and writing code just for Firefox. But I was writing an article recently and was told it would make sense to try to support Chrome. Here is what I had to do to make my article work in both browsers. Supposedly Chrome will soon support the spec so this won't matter. Till then, I hope this article is helpful for folks.

Before we get started, let's get the vendor prefix issues out of the way. Here is some code I modified from MDN to simplify my code:

The first thing I ran into involved objectStore creation. According to the spec, you can only create new objectStores when the version changes (you specify a version when you open the IndexedDB). Consider the following code:

When run in Firefox, it will correctly notice your first time run and run onupgradeneeded. I go the extra step to be really sure and check the objectStoreNames property as well.

Chrome, unfortunately, doesn't run this at all. Instead, you have to manually set the version and use the success handler for that request. Here is an expanded version of the code that supports both Firefox and Chrome.

You can see where my onsuccess for opening the connection checks the objectStoreNames properties and if necessary, runs setVersion. That returns a request object that I can use in an onsuccess handler in to create my store. Technically I've got a bit of DRY violation going on here with the objectStore definition, but you can get the idea. When Firefox runs this code, it will run onupgradeneeded first (on the initial run) so when it gets to the onsuccess for openRequest the objectStore is already created.

Once that problem was solved, the next issue I ran into was with the static constants I used to open transactions. And here is where living on the bleeding edge is not terribly fun. My initial code worked in Firefox but not in Chrome. I then made it work in both. I then updated Firefox to 13 and it stopped working. I then fixed it up for both. But wait for it - the constants are also going away in the latest spec. So given this code:

We need to change it to...

Woot. Specs are fun! Let me leave you with one last little tip. Need a quick way to get the count of an objectStore? This method will get and return the value to a callback.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA

Archived Comments

Comment 1 by Jake Drew posted on 7/18/2012 at 4:12 AM

It seems impossible to create an index via createIndex after a table has been created. What I mean is that I cannot seem to get a direct reference to an objectStore in javascript without using createObjectStore.

I have tried several ways like:

var objectStore = window.IDBTransaction.objectStore("myOS");

No luck so far. This would be nice for creating an index on a pre-existing table during a version update. Any suggestions?

Comment 2 by Raymond Camden posted on 7/18/2012 at 7:11 AM

I believe you can only open it via a transaction.

foo=db.transaction(["employee"], "readwrite").objectStore("employee")

The resulting object has a createIndex method.

Comment 3 by Raymond Camden posted on 7/18/2012 at 7:12 AM

Note the use of a string: "readwrite" This is how you do transaction types in most recent browsers.

Comment 4 by Odin Hørthe Omdal (odinho) posted on 7/19/2012 at 3:24 AM

Haha, yeah, sorry for the string constants, but it's all for the long term health of the web, promise crossed pinky fingers.

Anyway, Firefox still works with the constants, at least my nightly. They are not really bad, IDBTransaction.READ_WRITE now returns "readwrite" and it's no problem having them there IMHO. They are just a bit uglier than "readwrite", but at least far better than 1, which would otherwise be what people would use when writing code. :-S

IE10 will include the constants, as I said, I think Firefox has them now, -- and I think we'll put them in Opera too. No real big drawbacks as far as I can see, and we don't want to get compatibility problems ahead.

Comment 5 by Raymond Camden posted on 7/19/2012 at 3:36 AM

Odin (kick ass name btw ;), were you involved in the spec here?

Also - I'm having a hard time parsing your reply. It was my understanding that the strings were what you should use now - not the constants.

Comment 6 by Odin Hørthe Omdal (odinho) posted on 7/19/2012 at 11:49 AM

I made the bug for the change, and lobbied it through with the help of a few others. :-)

I do spec-work for Opera on IndexedDB.

Before the constants were numeric: IDBTransaction.READ_WRITE gave you a numeric 1 as a value.

Authors were expected to write code like transaction('mystore', IDBTransaction.READ_WRITE). Only rockstar programmers (like you) would've done that. Most people wouldn't bother, and it would quickly look like: transaction('mystore', 1). Just look at checking readyState in XHR for an example... :-)

After the change the constants (IDBTransaction.READ_WRITE) were removed from the spec. However, instead of removing them from the implementations, at least Microsoft kept them so that old code would continue working. Ofc. it has to not be too old, so that it doesn't use the horrible .setVersion() version of the spec.

So what Microsoft did, and I believe Firefox as well, was to make those constants rather return their new string value. So that code written using IDBTransaction.READ_WRITE would return "readwrite" rather than 1 now.

If people update their code and remove the IDBTransaction.READ_WRITE's therein, we could actually remove it from browser implementations. However, normally, whatever you put onto the web platform stays there and has to stay there forever in order to not break web pages... And I don't really think that having some extra constants defined is all that much problem.

If we can remove them, maybe we should do that, if we can't we can't, and that wouldn't really be a huge problem IMHO.

Comment 7 by Raymond Camden posted on 7/19/2012 at 6:47 PM

Thanks for the history heed Odin - it is great to hear from an insider's view. Mind another question? (I'm going there anyway... ;) I've made no secret of the fact that while I think IndexedDB is ok, I really wish WebSQL would have been the "winner." That being said, the crucial thing missing from IndexedDB is more complex ways of searching. Will we ever see an improvement in that area? Mentally I tend to equate IndexedDB with Mongo, which I know isn't the case, but it would be nice if more in-depth searching was allowed (even if it had a performance penalty).

Comment 8 by Odin Hørthe Omdal (odinho) posted on 7/19/2012 at 7:23 PM

There is much talk of a IndexedDB v2. When we've got several implementations out of the door, and things are settling down well etc. At that point we will look at how it is used, what people *want* to use it for, (new/added use cases), what the pain points are etc.

We will never be able to backward incompatible changes (it's the web, man), unless it's stuff that actually no-one is using.

So, yes. Definitely opening for more advanced searching, I think it's in the wiki for "what we want to do with IDBv2" already. However, so far I haven't seen any straw proposals on how it could work. If you're very interested in it, you could start researching that :-)

It'd be interesting to follow. But it will take some time until we will look at it in the working group.

Problem with WebSQL is that we would've had to define SQL, and not getting a really stable platform, but it would've mostly just been "do whatever SQLite does". Which is not good.

However, I think we think we will keep WebSQL enabled and around, at least in the short term. I have a few kiosk-projects myself doing much searching that is using WebSQL.

Comment 9 by Raymond Camden posted on 7/20/2012 at 2:57 AM

Query - why do you think following SQLite isn't good? I've used it quite a bit in the past and it's always worked very well. I just feel like the decision was made w/o much thought of the practical impact. The amount of people who knows SQL (especially in web dev) versus a NoSQL/Index type tech is waaaay in favor of SQL. Also, WebSQL is supported on mobile now but not IndexedDB. (Sorry - don't know if Opera Mobile has it or not.)

I know there is no chance of this changing, but.... I'm going to grumble about it. ;) (And continue to get better with IndexedDB.)

Comment 10 by Mason posted on 11/2/2012 at 10:23 PM

" I just feel like the decision was made w/o much thought of the practical impact. ..."

Oh you said a mouthful. I can't believe the NoSQL fanboys found a way to butcher WebSQL too. I guess we're going to have to wait for yet more projects to completely fail because NoSQL is a totally inadequate implementation for most kinds of complex application data. Eventually the W3C will fire the NoSQL fanboys and we'll have a real data spec again.

It's like watching republicans try to balance a checkbook.

Comment 11 by RoadHalk posted on 3/13/2014 at 7:46 PM

Need Help

I am new with jscript and indexdb. But I have been trying to create some functional structure to CURD in to indexdb.

Kindly suggest, Why I have to (on occasion) click multiple times to submit or retrieve the data.

I really appriciate your help.

Comment 12 by Raymond Camden posted on 3/14/2014 at 5:51 AM

Can you put the actual live version online for me (and others) to try?