Tutorial: Working Around IE6’s Caching of AJAX Content
March 17th, 2007
Microsoft, in their infinite wisdom, decided that it would be most efficient to cache any content returned by “ActiveXObject(“Microsoft.XMLHTTP”)”, the driver behind the now ubiquitous AJAX functionality.
The symptom you’ll see is that the results displayed when requesting AJAX content is actually stale and no amount of refreshing–even of the page itself–will force new content to appear. The old “pragma no-cache” solution that forces IE6 to get the refreshed page’s content from the server does not apply here.
The real-world example I’ll give is of the Live Scoring scoreboards we use on McKinneyNews.net. Here, we display a graphical scoreboard and accompanying text updates that follow a game in real-time. To avoid a mini-DDOS attack by having everyone constantly refreshing the page every few seconds (a story for another day), we implemented these scoreboards as AJAX elements that update every 30 seconds. As this feature started getting more popular, we started hearing from more and more users that the scoreboards were simply not updating when indicated, and, in fact, often reverted back to an earlier score.
The culprit turned out to be this caching bug feature in IE6. The solution is actually easy to implement.
Let’s say you have a generic AJAX setup as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// JavaScript Document
function createRequestObject() {
var ro;
var browser = navigator.appName;
if(browser == "Microsoft Internet Explorer"){
ro = new ActiveXObject("Microsoft.XMLHTTP");
}else{
ro = new XMLHttpRequest();
}
return ro;
}
var http = createRequestObject();
function sndReq(divId, procpage) {
http.open('get', procpage);
http.onreadystatechange = handleResponseGen;
http.send(null);
}
// generic updates
function handleResponseGen() {
if(http.readyState == 4){
var response = http.responseText;
var update = new Array();
if(response.indexOf('|' != -1)) {
update = response.split('|');
document.getElementById(update[0]).innerHTML = update[1];
}
}
}
|
You’ll notice that the sndReq function accepts the procpage variable. This is the path to your PHP AJAX processor page, plus any query parameters. For example:
/inc/ajax_do_something.php?id=3
This is the crux of the problem. In this example, we’re calling the same “id=3″ over and over again. P.O.S.6 IE6 sees this repeated URL and thinks to itself, “Self, I’ll just save my user a lot of time and effort and use the cached version of this content.” IE6, you would be wrong. The assumption that the AJAX content would be the same is asinine. AJAX content by definition is dynamic, so I can’t think of a case in which it should be cached. Regardless, IE6 does this.
The way around it is to beat IE6 at its own game and provide a pseudo-unique URL for the AJAX request. This is easily accomplished by adding a randomly generated number as an additional (and superfluous) URL parameter. Time codes work well and are more or less guaranteed to be unique. However, 99.99% of the time, a simple random number is all that’s needed.
An updated sndReq function and a new, simple pseudo-random number generator is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
function sndReq(divId, procpage) {
// tack on a random number. This provides a psudo-unique
// key that forces IE to NOT cache the AJAX content.
procpage=procpage+"&rand="+calcRand();
http.open('get', procpage);
http.onreadystatechange = handleResponseGen;
http.send(null);
}
function calcRand() {
var retVal = Math.floor(Math.random() * 1001);
return retVal;
}
|
With the somewhat unique query parameter, IE6 thinks that it is calling something new and does not revert to its cached version of the content.
Problem fixed.
Sphere: Related Content


