The Model
The Model is in charge of loading data from the server via AJAX, and caching that data locally to minimize duplicate AJAX calls. The Model is does not have any UI code at all, and has zero application logic – it’s strictly in charge of loading data (and in later phases, saving and deleting data).
Setting up the Model
Let’s start the walkthrough of model.js on line 3:
/** * our local cache of data */ var cache = new Array(); /** * a reference to ourselves */ var that = this; /** * who is listening to us? */ var listeners = new Array();
First we need to create a place to store our local cache of data. It’s also handy to have a reference to ourselves for use in other inner functions later on. Lastly, we need to keep track of who is listening to the Model, so we can notify them when important things happen in the Model. Now that we’ve got our definitions out of the way, let’s take a look function by function.
Loading and Managing Data
We’ll start with what will likely be more commonly used functions: getItem() and getAll(). (Since both of these functions are nearly identical, I’ve included only getAll() below). These are public methods of the Model that the Controller will use to request data.
/** * load lots of data from the server * or return data from cache if it's already * loaded */ this.getAll = function(){ var outCache = toArray(); if(outCache.length) return outCache; that.notifyLoadBegin(); $.ajax({ url: 'ajax.php', data : { load : true }, type: 'GET', dataType: 'json', timeout: 1000, error: function(){ that.notifyLoadFail(); }, success: function(data){ loadResponse(data); that.notifyLoadFinish(); } }); }
The purpose of the getAll() function is to return data if it has any in it’s local cache, or to request data from the server if the cache is empty. Let’s step through getAll() line by line to get a better understanding of exactly what’s going on. First, on lines 68 and 69, we check the local cache to see if we even need to make an AJAX call or not. If the cache has data, just return it outright and we’re finished.
Managing Our Cache
Notice that we make a call to toArray(), a local function that converts our cached data into a normal Array object. Remember, our cache object (line 6) act more like a hash table than an Array, so we can’t just return that straight away. We don’t want whoever calls this function to have a mutable reference to our cache object – we need to enforce that the Model is the only object that has control of the cache object.
On line 70, we’ve determined that our cache is empty and that we’ll need to make an AJAX call to load in the data, and this line notifies all of our listeners that we’re starting that process.
Lines 71 through 84 actually make the AJAX call. In the event of an error (like a 404 for 501 server error), we simply notify all of our listeners of the problem and exit out. When the AJAX is successful, we pass the json response data to our loadResponse() function, and then notify all of our listeners that we have finished loading in new data. Easy!
Now let’s take a look at the loadResponse() function, since this is where we’ll be managing our cache directly.
/** * load a json response from an * ajax call */ function loadResponse(data){ $.each(data, function(item){ cache[data[item].id] = data[item]; that.notifyItemLoaded(data[item]); }); }
As we load in each data item, we’ll store it into our cache. Since our cache is going to act like a hash table, we use each items unique id as it’s key. After loading each item in to the cache, we notify all of our listeners that it’s been loaded.
Model Listeners
When notifying our listeners about a new item, the notification function is just like those described in the View, but we also pass in the item that’s been loaded:
/** * tell everyone the item we've loaded */ this.notifyItemLoaded = function(item){ $.each(listeners, function(i){ listeners[i].loadItem(item); }); }
Adding and creating listeners for the Model work just like the View, so I won’t go over that code again here.
Summary
In summary, we’ve now created a Model that has exactly 1 responsibility: to manage data. the Model can load data on demand, notify listeners when data has been loaded (or when that process fails), and can cache that data so we don’t make needless AJAX calls to the server. We’re well on our way to an MVC optimized web app! Next up: the Controller.
Has the line numbering slipped by 1 in Loading and Managing Data ?
hi, we can used some HTML5 local storage for to get more good performances http://madhukaudantha.blogspot.com/2011/04/html5-local-storage.html
Thank you so much. This was really helpful getting the concept clear. May I request you to provide a dummy application like this implementing MVC using YUI.