local caching and JSON bugs.

Published 2006-12-22 13:00:00
One of the projects I'm working on is using XUL to render data, we started testing a few weeks ago, and discovered that the load times/ response where quite bad. It was pulling too much data from the server, and the application would either hang (if we didn't use asyncrounous xmlhttprequest calls), or we would have to show a slidy to indicate that data was being loaded. Neither where ideal.

In discussing the application with the client, they also requested that the application remember some of the states (eg. the data filters). Normally you might consider cookies or having a preferences database, but I remember seeing something about firefox2 having localized session storage.

You can read the session storage specification here, It allows you to store strings totalling upto about 5Mb on the client side. However, the reality is that you really need to be able to store javascript objects or similar in it. So since we where using JSON to transfer data, I thought 'how about serializing the data back into JSON, and storing it in the session.'

I started off by using the JSON js code, however this code is unusable for 1 major reason - it adds a method to array's/objects, resulting in the fact that foreach() always returns an additional member. (breaking almost all the existing javascript code!) - I also ran into problems with recursion in firefox (but I think thats due to me forgetting to add the String.prototype method.)

So in the extended entry is a quick kludge (without full unicode support) for converting items into JSON in javascript, so that something like this works:

sessionStorage.setItem("mycache_somedata", JSON_toString(mydata));

... and onloading..

var mydata = new Array();
if (sessionStorage.getItem("mycache_somedata")) {
eval("mydata = " + sessionStorage.getItem("mycache_somedata").value);
}

Quick JSON.js - without unicode support.



/**
* Standard JSON encoder.
*/

JSON_toString = function (obj) {
function df(n) {
return n < 10 ? '0' + n : n;
}
var m = {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
};
switch(typeof obj) {
case 'string':

// fixme - this needs to do better escaping!
var ret = '"';
for(var i = 0;i<obj.length;i++) {
if (m[obj[i]]) {
ret += m[obj[i]];
continue;
}
ret += obj[i];
}
return ret + '"';

case 'boolean':
return String(obj) ;

case 'date':
return '"' + obj.getFullYear() + '-' +
df(obj.getMonth() + 1) + '-' +
df(obj.getDate()) + 'T' +
df(obj.getHours()) + ':' +
df(obj.getMinutes()) + ':' +
df(obj.getSeconds()) + '"';


case 'number':
return isFinite(obj) ? String(obj) : "null";

case 'object':
return JSON_ObjectToString(obj);

case 'array':
return JSON_ArrayToString(obj);

default:
return '';
}

};



function JSON_ObjectToString(obj)
{
var a = ['{'], b;

function p(k, s) {
if (b) {
a.push(',');
}

a.push(JSON_toString(k), ':', s);
b = true;
}


for (var i in obj) {

if (!obj.hasOwnProperty(i)) {
continue;
}

var v = obj[i];
switch (typeof v) {
case 'undefined':
case 'function':
case 'unknown':
break;
case 'object':
if (!v) {
p(i, 'null');
break;
}
default:
p(i, JSON_toString(v));
break;
}
}
//alert('keys = ' + tmps);

a.push('}');
//alert(a.join(''));
return a.join('');
}


function JSON_ArrayToString(obj)
{
var a = ['['], b, l = obj.length;

function p(s) {
if (b) {
a.push(',');
}
a.push(s);
b = true;
}

for (var i = 0; i < l; i += 1) {
var v = this[i];
switch (typeof v) {
case 'undefined':
case 'function':
case 'unknown':
break;
case 'object':
if (!v) {
p("null");
break;
}
default:
p(JSON_toString(v));
}
}
a.push(']');
return a.join('');
}

Comments



Add a comment (requires javascript!)
Name
Email
Homepage
Comment Title
Comment
I am a link spammer?