using Javascript to refresh an image without a cache-busting parameter
…say you’re using Javascript to reload an image periodically, say, every 60 seconds, and the image never refreshes. If you look for help across the web (as undoubtedly you have, since you’re here now, right?) you’ll find a) A bunch of people telling you to tag on a url param that’s a random number, and b) A bunch of snippy JS people who will insist, very condescendingly, you haven’t set your response headers correctly, and it’s not javascript’s problem, and you should think before you post such stupid questions.
Well, it turns out they’re both wrong. With the latter, the problem is, a browser has an internal page-level memory space that it will “remember” image urls with. When you create an image in javascript (via an Image() object or innerHTML, take your pick), if that image src has already been requested once on that page, the browser will give you that image from its internal memory, regardless of the image’s Expire or Cache-control headers. It won’t be put into the browser’s cache, sure, but it still stays in the browser’s memory for as long as you’re viewing that page.
The former seems to be the quick fix - the image src is always unique, so it’s not in memory, and the browser will ping the server for the image. But this approach fails if you’ve actually set your target image’s headers correctly (which of course you should). Because with this approach, the server sees each request as unique, and will send a new copy of the image down the pipe, regardless of if you wanted it to or not. You’re similarly screwed if you’re working on a high-traffic sites using a CDN - since a CDN (usually) contains cached copies of files from a master server, adding the cache-busting parameter to an image on a CDN will force the CDN to re-acquire the image from the master server before sending the image, which defeats the whole purpose of using a CDN in the first place.
The solution, unfortunately, is pretty hacky - to add a hash mark (#) to your image before applying a cache-busting parameter, i.e.:
function updateImage() {
document.getElementById('image_arena').innerHTML = '<img src="/your/constantly/updating/image.jpg#e' + Math.random() + '">';
setTimeout(updateImage, 60000);
return;
}
This will psyche out the browser into thinking the URL of the image is unique (”Hey Firefox, look over there! PSYCHE!!11!”), but in the actual HTTP request anything beyond the hash gets stripped before the request is made. So, the browser thinks the request is unique and pings the server for it, but the server will know for reals wether or not the request is new, and send the appropriate 200/304 response*. Everyone’s happy, except for possibly your sense of aesthetics, since that is an ugly url you’re passing. But since you’re the only one who will probably see them, you’ll be alone in your secret shame.
*Yes, I did just bust some HTTP response codes.
