The Ajax Caching Trap

A problem that frequently occurs when using Javascript to perform an Ajax call is that the data returned to the client from the server via an Ajax call is not current but cached. A sympton of this effect is that the returned data does not change from call to call but remain constant in spite of the fact that the data on the server side has indeed changed. This problem occurs when the URL String for subsequnt Ajax calls is constant. Some browsers cache the returned contents of the Ajax call. If the URL is the same as the previous call an actual request to the server is not performed and the browser returns the cached contents from the previous call.

Another symptom is that this problem persists even when one adjusts the header values returned by the ajax call. For instance I had the following header values which were to be returned via a PHP Ajax server routine.

header('Content-Type: text/xml');
echo $xml_string;

After much googling I changed to PHP code so that it returned headers which should have informed the client that the returned data should not be cached but be re-read every time. The code looked like this.

header('Content-Type: text/xml');
$now = gmdate('D, d M Y H:i:s') . ' GMT';
header("Expires: $now");
header("Last-Modified: $now");
header("Cache-Control: no-cache, must-revalidate");
header("Pragma: no-cache");
echo $xml_string;

Unfortunately this had no effect. The problem persisted and after spending many hours banging my head against the wall trying to determine what was going on, I came across a solution. After many hours of googling I found a solution which solves this problem by using a clever trick. Perhaps this small tip can spare some of you the agony that I endured. An example of a typical Ajax call in Javascript to a Server routine looks something like this

xmlhttp.open("GET", "ajaxservice.php?paramtervalue=2", true);
xmlhttp.onreadystatechange=ajaxhandlerfunction;
xmlhttp.send(null);

Even if the the data on the server side change from call to call some browsers will not return the changed data from the server but rather the cahced data stored by the browser on the client. Ths solution is to add an extra dummy parameter to the URL in the xmlhttp.open call which makes the subsequent URL to differ from the previous call. This makes the browser think that URL has changed and forces it to actually perform a call to the server and retrieve the updated data. A widely used solution is to append a random number to the URL as a dummy parameter. This has no effect on server side since the parameter value is ignored. An example would be the following.

xmlhttp.open("GET", "ajaxservice.php?paramtervalue=2&dummy="+Math.random(), true);
xmlhttp.onreadystatechange=ajaxhandlerfunction;
xmlhttp.send(null);

This solution is not only relevant for the URL in the Ajax call but can also be used in later references to data on the server. In one situation I had a constellation in which the call to the Ajax server changed an image file on the server so that it had different contents albeit using the same name. The client referenced this binary file directly using the following code.

document.getElementById("dynamicimage").src="ajaxbild.jpg";

This approached suffered from the same caching phenomenon as the previous examples of the Ajax call using xmlhttp.open. It was solved by using the same technique, i.e. using a dummy parameter to trick the browser ionto thinking that it must perform a call to the server to obtain the data. The solution is similar.

document.getElementById("dynamicimage").src="ajaxbild.jpg?"+Math.random();
Share

Comments

  • Anonymous says:

    Thank you! You saved me from 2 hours of headaches!


  • Anonymous says:

    didn’t save me from 2 hours of headaches, but probably saved me from suicidal insanity after it. seriously, thank you, totally fixed my problem!


Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>