Blog

17
February 2015

Gavin Pickin

WebSQL - When is a Javascript Object not a Javascript Object?

Cordova / Phonegap, Javascript, Mobile Development, Techie Gotchas, WebSQL

After a short break from WebSQL, I am back to talk to you about WebSQL again, as I continue my work on my Cordova / Phonegap cross platform app. Today I ran into one of those Gotchas, that cost me a couple hours of time trying to debug a strange happening in my app. It is one of those things in our developers lives, if you only knew what you didn’t know, you'd know more than you know now. In finding this gotcha, I remembered a couple of other lessons when using Web Developer tools, which you may or may not know… so I’ll share those too.

The context of the situation made it worse than it would have been normally, so I’ll skip most of it… and get down to the nuts and bolts. When you use WebSQL and create run a query, like below, you are returned a SQLResultSet, which has rows of items.

app.db.readTransaction(function (tx) {
          tx.executeSql('SELECT * FROM people',
               [],
               function( tx, peopleList ){ doSomethingWithPeopleList( peopleList ); },
                              errorCall
               );
          });
     });

 

You can access the first item in the Result Set by the following syntax.

var person = peopleList.rows.item(0); // from 0 to peopleList.rows.length-1

 

If you console.log( person ), you see a Javascript Object… which is really handy to work with, dot notation for property access, not too much reinventing the wheel… or so I thought.

My issue came up where I was passing this object reference through several functions, updating properties as necessary, and then passing the object back to be saved if the object was dirty. My problem was, it was never dirty… and therefore never updating.

First step was to console.log the object, at several steps in the process. Even before and after setting a property, the objects were identical. I decided to add a new property, and see if that made a difference. When I looked, all of my objects had the new property, but the old was unchanged. I started to think about async and possible conflicts, and thought I was losing my mind, when something triggered a memory. When using Web Tools to debug, and you console.log a javascript object, console.log uses references, so if you console.log it 3-4 times, when you view the log, they all look the same, because its a ref to the object, and how that object looked at last usage.

There is another console method, which works (usually in most dev tools, I have not tested them all) where you console.dir( person ) instead of console.log( person ) and it actually dumps the object at that point in time, and not just a reference. Good to know, and good to remember. I wonder how many of you have battled that one before.

Back to the main problem, why were some of the properties read only, but others were not. I even compared the same object as is, and then tried a JSON.parse( JSON.stringify( person )) and compared them… visually there was no difference. At this point, I finally found the magic words in google ( previous searches did not turn anything up ) and found a couple of posts on stack overflow. The tldr; WebSQL result sets in some implementations do indeed output an object with immutable properties.

http://stackoverflow.com/questions/19999906/websql-are-returned-rows-in-sqlresultsetrowlist-immutable

http://stackoverflow.com/questions/5093870/immutable-chrome-sqlite-return-objects

In short, if you are working with WebSQL results, the items returned are Javascript Objects (the title might be link bait, maybe), but it is quite likely, that they are read only Javascript Objects. There were several suggestions on how to change that, with Object.defineProperty and jQuery.extend() and _.extend().. and of course, the JSON.stringify and JSON.parse functions which convert the object into a string, and back again.

I am not sure if having the data as immutable or not is a good idea, it does make converting to use with localStorage to WebSQL more complicated. If you did convert from localStorage to WebSQL you could mask that in the DAO, although that seems to be a lot of work in preparation alone.

Having an immutable set of properties might be nice, to be able to add additional fields, so you could easily compare original and updated fields.
Knowing this, I can work around it, but it wasn’t easy to determine in the first place. In doing so, I remembered a key debugging tip with console.log and value vs references, and console.dir.

Hopefully others can learn from my tough learned lesson.

Blog Search