Building a Client-Side Ajax Cache: Caching Algorithms / Page 2 | WebReference

Building a Client-Side Ajax Cache: Caching Algorithms / Page 2


Building a Client-Side Ajax Cache: Caching Algorithms [con't]

Determining Freshness Using a Timestamp

The idea behind this strategy is that, by adding a timestamp to the resultset upon caching it, we will be able to calculate its age and compare it against the current date and time when we retrieve an item from the cache. We have two objects that could store the timestamp: the cache and the keyIndex array. However, there is a very good reason to not put it in the array, and that is that the item will be removed before the search results are displayed to the user. Since speed is a factor, the hash is the place to store it. As the code below demonstrates, we'll call a function called removeExpiredItem() when checking for a cached result. An expired item would then be discarded and a new one will be fetched from the server:

An object literal will contain both the output HTML and the timestamp:

We were using a Hash object to store cached items, but with the inclusion of the timestamp property and new method, we should promote the cache to its own class. Using the Class.create() constructor method, we'll supply the Hash as our base class, and add our method to it. The expiryInMinutes will be supplied to the AjaxCache constructor, along with the defaultURL and the maxSize, so that it knows how long cached items will remain fresh. Our internal cache object can refer to it when calculating an item's age.

The removeExpiredItem() function compares the object's timestamp to the current time. To find out whether or not an item has expired, we need to calculate its best-before date, by adding the expiryInMinutes variable to the timestamp. Internally, dates are stored as the number of milliseconds since Jan 1, 1970, so unless you want to do a lot of converting, it's best to use some of the Date functions to do the math. First, we'll create a new Date. Then, we can set it to the desired date and time using the setTime() function. It will add the number of milliseconds passed to it to Jan 1, 1970 to set the date. To add the expiryInMinutes to the timeStamp, we can use the setMinutes() function. Specifically, we'll use getMinutes() to get the timeStamp in minutes, and add the expiryInMinutes to it. The setMinutes() function will return the data in its raw format, so we can pass it directly to the setTime() function. The item has expired if it smaller (earlier) than the current date and time. Any items that fail the freshness test will be stripped from the cache:

Using a Periodic Service to Determine Freshness

A second method of managing cache freshness on the client-side is to periodically check the cache and delete expired items at that time. This can be achieved by using Prototype's PeriodicalExecuter class. All we need to do is pass it a function to call and the number of seconds for the interval. To check for expired items, we'll create a new cache method to iterate through all the cached resultsets, which will in turn call removeExpiredItem(). The new function, called checkForExpiredItems(), uses the Enumerable.each() function to apply removeExpiredItem() on every cached object. Notice that the this pointer is supplied to the each() function as the second argument. The removeExpiredItem() function needs to run within the cache's context because it refers to it when removing items (if (expired) this.remove(key);). The anonymous function argument to the each() function splits up the pair argument into two separate parameters. The context is sent along to the removeExpiredItem() function using the method:

Here's the files that I used to test my cache. They should provide a good jumping off point for developing your own client-side Ajax cache.

We've looked at a lot of options for caching data on the client, but there are a lot more that we haven't touched upon. For instance, there's the issue of persistent storage, where the page does get refreshed. Under those circumstances, it might be feasible to use cookies if you aren't trying to cache too much data. We also kept our focus on the client-side here. Server caching is a whole other subject, which I hope to explore in a later series. With Ajax usage on the rise, it is conceivable that caching frameworks may also hit the market, so keep your eyes open for that before investing a lot of time writing your own from scratch. Next up, we'll be looking at a related technique called Comet Programming. As you will see, it is highly relevant to the subject of data caching.

Original: March 5, 2009