January 2011 Archives

IndexedDB Status Report and Demo

| 20 Comments

Update: Kyle Huey of Mozilla has updated this example to work with the latest version of the API. This version works with Firefox 10.

Update, March 17th: things have gotten a lot better since I first posted this, and I've make a number of edits below. Big thanks to Ben Turner and Jeremy Orlow who explained a lot in the comments!

I've been trying to create an IndexedDB example for the next edition of my JavaScript book. IndexedDB is a promising API< strike>, but it turns out to be just barely useable right now.
I'm using Firefox 4b10 RC and Chrome 10.0.642 11dev. Here are some things I've found out. Maybe they'll help someone!

  1. Both Mozilla and Chrome prefix the global indexedDB object. Use mozIndexedDB or webkitIndexedDB. Prior to FF4b9, apparently you had to use moz_indexedDB, with an underscore, but no longer.

  2. Chrome also puts webkit prefixes before the other related globals IDBTransaction and IDBKeyRange. Firefox does not (currently) prefix those.

  3. I can't get Chrome to insert anything into a database. Even Google's tutorial at http://www.html5rocks.com/tutorials/indexeddb/todo/ isn't working. It complains that the DB is in read only mode and won't insert. Tested on Linux and MacOS. This is presumably a regression of some sort since the tutorial must have worked on Chrome at some point. It doesn't even work if you launch chrome with the magic --unlimited-quota-for-files which you need when using the filesystem API.

  4. For large databases, like my demo, you have to start Chrome with --unlimited-quota-for-indexeddb

  5. Chrome's error codes are off-by-one compared to the IndexedDB spec. They still differ from the spec, but Firefox now matches Chrome for most of the codes.

  6. The spec never defines what a "key path" is. The non-normative examples show it as a plain string. When creating an object store, FF requires an object like {keyPath:"property_name"} instead of just the "property_name" string. Google's examples show key paths like this, too, so they're apparently both out of sync together on this point. In comments, Ben and Jeremy explain that the spec was out of date.

  7. But it gets weirder. When creating an index on an object store, Firefox wants a plain string key path, and the index won't work if you specify an object.
    Ben explains this in comments.

  8. It is completely undocumented in the spec how you would express a key path for more deeply nested properties of the object being stored. An array of strings seems like the right thing to me, if anyone wants to take my advice. [Ben explains in comments that this issue has been deferred for a future revision of the spec.]

  9. Finally, Firefox has diverged from the spec in one major way. There are lots of places where you make async requests in this API. The spec says that the result of your request will be in the request property of the event object that is passed to the onsuccess event handler. But Firefox has (relatively recently, I gather) moved the result value so that it is a property of the request object rather than the event object.. Instead of writing event.result, as the spec says, in Firefox you have to write request.result, or perhaps more elegantly: var result = event.result || event.target.result; Thhe spec was out of date, and Chrome has now followed Firefox. Now, you always get the result of an asynchronous operation from the result property fo the request object. The event object is no longer used.

  10. Neither Firefox (See Ben's comment below for directions on accessing the Firefox UI) nor Chrome have any UI yet for managing the databases created by this API. So if you mess up a database and want to delete it, you just have to find your profile directory and delete the appropriate file or directory there. This is the command I used on my Linux machine:
    rm -rf ~/.config/google-chrome/Default/IndexedDB/*localhost*.indexeddb ~/.mozilla/firefox/*.default/indexedDB/*localhost*

  11. I've just assumed that this API won't work right if you test it from a local file, so I've been running a simple node-based webserver. (That's why the database names shown above have "localhost" in their names).

My zipcode demo (written for the next edition of JavaScript: The Definitive Guide) loads a database of US postal codes and lets you search by postal code or by city name. It seems to work today in FF4b10RC1 and Chrome 11dev on Linux. I haven't tested Windows. or MacOS (The database includes latitude and longitude, so it would be sweet to hook it up to google maps!)

Update: Google's demo mentioned above can be made to work on FF4b10 by applying this patch.

Update 2: I've cleaned up my demo considerably and have updated the link above.

Update 3: Thanks to Guido Tapia who suggested in comments that I try the Chromium nightlies. This example sort of works with Chromium 11.0.652.0 (72925). The API works, so I think my example code is written correctly. But chrome's database engine can't handle all the zipcodes. It looks like it downloads one batch of a few thousand, then takes so long to process them that the next "onprogress" event gets the rest of the zipcode file. And this version of chrome can't insert 30000+ objects at once. It pegs my cpu and tries for 20 to 30 seconds then aborts the transaction. (I was surprised how slow Firefox was to insert all these zipcodes, but this version of Chrome is slower, and doesn't actually succeed...) This problem is fixed by adding the --unlimited-quota-for-indexeddb when you launch Chrome.

console.log() for Web Workers

| 6 Comments

Web Workers are threads for client-side JavaScript. There are a lot of very cool things about them, but one of the not-so-cool things about them is that it is hard to debug code running in a worker thread. Worker's don't have access to the DOM. They can't call alert(), they can't modify the document and they don't have the console.log() API that we've all come to depend on.

I've put together a proof-of-concept implementation of console.log() for web workers. Drop the WorkerConsole.js script into your HTML file, and (in theory, anyway) your worker threads will all be able to call console.log. there are lots of caveats, though. See the comments at the top of the file.

It works by creating a MessageChannel (which means it won't work in Firefox) over which the worker can send logging messages back to the main thread. In order to create this MessageChannel, WorkerConsole.js replaces the Worker() constructor. It also forces each new Worker object to load and execute WorkerConsole.js first (to define console.log()) before executing whatever script you passed to the Worker() constructor.

You can find the code, and a very simple test at github.

5 Things You Might Not Know About jQuery

| 2 Comments

I've just posted a short article about jQuery over at O'Reilly Answers. Basically, it is 5 excerpts from jQuery Pocket Reference lightly edited and jammed together into an article. I tried to select jQuery features that are useful but obscure. See what you think!

Books

ECMAScript 5 & HTML5!

"A must-have reference"
Brendan Eich,
creator of JavaScript

JavaScript graphics makes web programming fun again!

Read Less, Learn More

Comprehensive coverage of Ruby 1.8 and 1.9

"The New Most Important Ruby Book"
Peter Cooper,
rubyinside.com

The classic Java quick-reference

About

Advertising

Pages

Hosted By

Powered by Movable Type 4.21-en