pStorage, A PersistJS Wrapper for AJAX

I Recently came across PersistJS when I wanted to build a caching layer for AJAX response in the browser. Being a Chrome-Only guy, I automatically went for sessionStorage as my option.

Unfortunately, neither sessionStorage or localStorage are a standard that works for browsers such as the mighty (giggle) IE. So I went looking for something generic that will work cross-browser. eventually I found PersistJS, and after some testing I found that it fits my needs as it wraps around different client storage techniques which means using it will deliver on my browser agnostic needs.

Since I could not find a simple wrapper that will meet my needs, and since I saw TONS of requests for this stuff during my search, I decided to build a simple class for anyone that may need it.

PersistJS shortcomings

What I found a bit annoying in PersistJS is that it lacks:

  • Content Verification, to makes sure that the user gets a refreshed content if there is any change in the server content
  • Time To Live (TTL). as part of the concept of building local storage to cache your AJAX response, is to be able to refresh it when relevant.

pStorage

The solution I came up with uses the wonderful CryptoJS for md5 hash, and PersistJS for client storage. So I wrote a class that can be embedded in your JavaScript and allow that missing functionality. I called it pStorage.

Note, if you want to make the client storage side a bit more tamper proof, you can include a salt, and add server side code that generates the “salt” parameter in gStorage, every time that a session begins, or even force it to change after TTL. in my example here, I wanted to stay generic.

Here is the code:

/*
 * pStorage
 * --------
 * a wrapper around PersistJS an CryptoJS to allow TTL and Content Validation
 * by Barry Shteiman, 2014, ref:www.sectorix.com
 */
var pStorage = new function() {
    this.uid = 'my_pStorage';
    this.salt = '';
    this.datastore = new Persist.Store(this.uid);
    this.get = function get(key) {
        var entry = JSON.parse(this.datastore.get(key)||0);
        if (!entry) return null;
            if (entry.hash !== this.hash(entry.value + this.salt)) {
                this.datastore.remove(key);
                return null;
            }
            if (entry.ttl && entry.ttl + entry.now < this.now()) {
                this.datastore.remove(key);
                return null;
            }
            return entry.value;
    }
    this.set = function set(key,value,ttl) {
        this.datastore.set( key, JSON.stringify({
            ttl   : ttl || 0,
            now   : this.now(),
            hash  : this.hash(value + this.salt),
            value : value
        }) );
    }
    this.del = function del(key) {
        var entry = JSON.parse(this.datastore.get(key)||"0");
        if (!entry) return null;
        else {
            this.datastore.remove(key);
            return null;
        }
    }
    this.now = function now () {return+new Date}
    this.hash = function hash(value) {return CryptoJS.MD5(value).toString();}
}

Note, you can and should change the uid parameter to be unique to your application (replace ‘my_pStorage’ with the name of your application for example)

The functions  implemented are:

  • pStorage.get(key) – retrieve data, returns 0 if nothing found
  • pStorage.set(key,value,ttl) – save data in the storage
  • pStorage.del(key) – delete an item

HTML

To use the complete mechanism you will need to call both CryptoJS (either directly from googlecode or download the file) and PersistJS.

<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/md5.js"></script>
<script src="ext/js/persist-min.js"></script>


The call itself is very easy, and a simple Ajax function can be built to incorporate the functionality.

JavaScript

Here is a simple example for an Ajax call (via jQuery) that looks for the data in the client storage, and if TTL is past, if content is different, or if it simply does not have it in cache – the call goes to the Ajax call.

function cachedJsonAjax (url,ttl,params) {
    var output;
    if (pStorage.get(url) == null) {
        output = $.ajax({
            url: '/path/' + url + '.php',
            type: 'POST',
            data: params,
            dataType: 'json',
            async: false
        }).responseText;
        pStorage.set(url, output, ttl);
    } else
        output = pStorage.get(url);
    return output;
}

All that is left, is to call this function, and point it to the right server resource in order to populate the data, relying on this caching layer in the front.

While this is all extremely simple, I hope this helps someone and saves you time :)

Leave a Reply

Your email address will not be published. Required fields are marked *

*
*