4

I have a calendar application and it loads all of the event data using ajax and json results. the issue is that i have different view and right now i have to re call the server when i change views.

Is there any recommendation for ways i can cache this data on the client side and check if i have loaded these events already before firing off more ajax calls.

What is the best practice for this ?

hvgotcodes
  • 118,147
  • 33
  • 203
  • 236
leora
  • 188,729
  • 360
  • 878
  • 1,366

3 Answers3

2

Like hvgotcodes said, an MVC framework would help; try backbone.js (http://documentcloud.github.com/backbone/), for instance.

Alternatively, you might want to consider using jStorage (http://www.jstorage.info/). Every time you need to make an AJAX call, check first if it's in your storage object, then run the AJAX call if it isn't. On the other end, whenever you finish an AJAX call, store the results in the storage object. Make sure you have some kind of index (a CalendarEvent id) to reference when looking it up in the data store. Might want to add some kind of "expire time" to the data in your storage, too ... a timestamp after the AJAX call, and re-request up front if it's out of date.

Ben
  • 126
  • 7
1

It's called MVC.

You need to construct a data model for you application, write some sort of Record objects, and then you can determine their status. So your application would have some sort of CalendarEvent model, and when you load data from the server, you would instantiate instances.

So when changing views, you would first check to see if you had the model object for that view, and if you did, you wouldn't need to load it from the server (unless you want to check for changes).

Your scheme doesn't need to be that complicated. If you load events by Id, you can do something like

window.App = {};
window.App.Models = {};

when you load a record you could put

window.App.Models[id] = InstanceOfYourRecord

and that way its pretty fast to look for records. Or just use a framework (like Sproutcore) that has a robust data layer.

hvgotcodes
  • 118,147
  • 33
  • 203
  • 236
0

I had similar issues on a recent project.

Conceptually, I have the "real" data model (DM) kept on the server, persisted to a database.

To make life sane, the client keeps its own local data model. Outside of the client DM, all the client code thinks it's pulling results locally.

When reading data (GET) from the client DM it:

  • checks the cache for existing results
  • invokes appropriate AJAX queries when cached data is not available, then caches the results.

When changing data (POST) via the client DM it:

  • invalidates the cache as appropriate
  • invokes appropriate AJAX queries
  • emits custom jQuery event indicating client DM changed

Note that this client DM also:

  • centralizes AJAX error handling
  • tracks AJAX calls still in-flight. (Lets us warn users when leaving pages with unsaved changes).
  • allows a drop-in, dummy replacement for unit testing, where all the calls hit local data and are completely synchronous.

Implementation notes:

  • I coded this as a JavaScript class called DataModel. As the design becomes more complex, it makes sense to further break-down the responsibilities in to separate objects.
  • jQuery's custom events let you easily implement the observer pattern. Client components update themselves from the client DM whenever it indicates data has changed.
  • JSON in your remote API helps simplify the code. My client DM stores the JSON results directly in its cache.
  • The client dm function arguments include call-backs so everything can naturally be passed along via AJAX when needed: function listAll( contactId, cb ) { ... }
  • My project only allowed single user logins. If outside parties can change the server datamodel, some sort of has-data-changed probe should be fired regularly to ensure the client cache is still valid.
  • For my app, multiple client components would request the same data when receiving a client DM changed event. This resulted in multiple AJAX calls with the same info. I fixed this problem with a getJsonOnce() helper, which manages a queue of client component call-backs awaiting the same result.

Example function in my implementation:

listAll:
function( contactId, cb ) {

  // pull from cache
  if ( contactId in this.notesCache ) {
    cb( this.notesCache[contactId] );
    return;
  }

  // init queue if needed
  this.listAllQueue[contactId] = this.listAllQueue[contactId] || [];

  // pull from server
  var self = this;
  dataModelHelpers.getJsonOnce(
    '/teafile/api/notes.php',
    {'req': 'listAll', 'contact': contactId},
    function(resp) { self.notesCache[contactId] = resp; },
    this.listAllQueue[contactId],
    cb
  );
}

The getJsonOnce() helper makes sure that if multiple client components request the exact same (uncached) data, that we only send out a single AJAX request and inform everyone once it comes in.

The notesCache is just a simple javascript object:

this.notesCache = {};
nsanders
  • 12,250
  • 2
  • 40
  • 47
  • but how would i cache the json results on the client side ? – leora Dec 09 '11 at 00:37
  • Added an example from my own code to show the caching in action. The helper function first caches the JSON result. It then invokes the callbacks of everyone waiting for that result. (The listAllQueue part). – nsanders Dec 09 '11 at 00:51