An AJAX Caching Strategy
by Bruce Perry
|
Pages: 1, 2, 3
Import the JavaScript
The web application uses script tags in the HTML to import the necessary JavaScript, including the Prototype library. The first xml.com article I wrote on this application shows how to download and set up Prototype.
<head>...
<script src="http://www.eeviewpoint.com/js/prototype.js" type="text/javascript">
</script>
<script src="http://www.eeviewpoint.com/js/eevpapp.js"
type="text/javascript">
</script>
..</head>
Set Up the Refresh Buttons
First I'll show the code from eevapp.js that I used to get the energy prices. Then I'll show the object that acts as a kind of request filter.
//When the browser has finished loading the web page,
//fetch and display the energy prices
window.onload=function(){
//generatePrice method takes two parameters:
//the energy type (e.g., oil) and the id of the
//span element where the price will be displayed
generatePrice("oil","oilprice");
generatePrice("fuel","fuelprice");
generatePrice("propane",
"propaneprice");
//set up the Refresh buttons for
//getting updated oil, gasoline, and
//propane prices.
//Use their onclick event handlers.
$("refresh_oil").onclick=function(){
generatePrice("oil","oilprice"); }
$("refresh_fuel").onclick=function(){
generatePrice("fuel","fuelprice"); }
$("refresh_propane").onclick=function(){
generatePrice("propane",
"propaneprice"); }
};
The code comments explain what's going on here. The one odd syntactical segment that needs explanation is the $("refresh_oil").onclick type of expression.
Prototype has a $() function that returns a Document Object Model (DOM) Element object. This Element is associated with the HTML id attribute that the code passes into the $() function as a string parameter. This syntax is the equivalent of writing document.getElementById("refresh_oil"), but it's shorter and therefore handier for the developer. What does "refresh_oil" refer to? This is the id of the Refresh button on the web page. See the left column in the browser screen depicted by Figure 1-1 for a view of the Refresh button.
<input type="submit" id="refresh_oil" .../>
The code sets the onclick event handler of this button to a function that will optionally seek to grab a new energy price. Optionally, meaning that our filter will decide whether or not to launch an HTTP request.
Check the CacheDecider Object First
The generatePrice() function first checks with a cache-related object called CacheDecider to determine whether a new HTTP fetch of an energy price can be initiated. Each energy category--oil, gasoline, and propane--has its own CacheDecider object. The code stores these objects in a hash named cacheHash. Therefore, the expression cacheHash["oil"] will return the CacheDecider object for oil prices.
If the CacheDecider or filter allows the code to make a new HTTP request (CacheDecider.keepData() returns false), then the code calls getEnergyPrice() to refresh, say, the crude oil price. The code comments explain exactly what's going on.
/*Check the CacheDecider object to determine if a new energy price should be fetched*/ function generatePrice(energyType, elementID){ //set the local variable cacher to the CacheDecider //object associated with oil, gas, or propane var cacher = cacheHash[energyType]; //If this object is null, then a CacheDecider object //has not yet been instantiated for the //specified energy type. if(! cacher) { //CacheDecider has a parameter that //specifies the number of seconds to keep //the data, here 24 hours cacher = new CacheDecider(60*60*24); //store the new object in the hash with //the energy type, say "oil", as the key cacheHash[energyType]=cacher; //Fetch and display the new energy price getEnergyPrice(energyType, elementID); return; } //The CacheDecider has already been instantiated, so //check whether the currently displayed energy price //is stale and should be updated. if(! cacher.keepData()) { getEnergyPrice(energyType, elementID);} } /* Use Prototype's Ajax.Request object to fetch an energy price. Parameters:energyType is oil, fuel, or propane.elementIDis the id of a span element on the web page; the span will be updated with the new data. */ function getEnergyPrice(energyType, elementID){ new Ajax.Request(go_url, {method: "get", parameters: "priceTyp="+energyType, onLoading:function(){ $(elementID).innerHTML= "waiting...";}, onComplete:function(request){ if(request.status != 200) { $(elementID).innerHTML="Unavailable." } else { $(elementID).innerHTML= request.responseText;} }}); }