views:

2653

answers:

10

It looks like that if I load dynamic content using $.get(), the result is cached in browser. Adding some random string in QueryString seem to solve this issue (I use new Date().toString()), but this feels like a hack.

Is there any other way to achieve this? Or, if unique string is the only way to achieve this, any suggestions other than new Date() ?

+5  A: 

another way is to provide no cache headers from serverside in the code that generates the response to ajax call:

response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );
miceuz
Incorrect. In IE, the no-cache headers are ignored for XMLHttpRequest calls, as discussed here: http://stackoverflow.com/questions/244918/internet-explorer-7-ajax-links-only-load-onceThe DateTime (or my .ajaxSetup method) are the only solutions that actually work.
Peter J
i've just pasted my usual no cache mantra, it's not stated that it's IE specific
miceuz
+4  A: 

Personally I feel that the query string method is more reliable than trying to set headers on the server - there's no guarantee that a proxy or browser won't just cache it anyway (some browsers are worse than others - naming no names).

I usually use Math.random() but I don't see anything wrong with using the date (you shouldn't be doing AJAX requests fast enough to get the same value twice).

Greg
Combine Date().getTime() together with Math.random() and you should be on the safe side. On a side note, Ext.Ajax also uses getTime() when disableCaching is specified.
vividos
A: 

Maybe you should look at $.ajax() instead (if you are using jQuery, which it looks like). Take a look at: http://docs.jquery.com/Ajax/jQuery.ajax#options and the option "cache".

Another approach would be to look at how you cache things on the server side.

finpingvin
Unfortunately, after some investigation, using $.ajax() and set cache = false will basically do the same thing. jQuery will add some random number to the querystring, and it doesn't check for existing querystring. So I guess using $.get() will suffice.
Salamander2007
Ah okey. Never tried it, just remembered i'd seen something about it in the docs :)
finpingvin
It's not even necessary to use $.ajax. Simply use .ajaxSetup.
Peter J
+3  A: 

I use new Date().getTime(), which will avoid collisions unless you have multiple requests happening within the same millisecond.

Mark B
I'm not sure why people keep voting this down, it's a perfectly good solution and is actually used internally by jQuery. If you're going to downvote this, at least leave a comment explaining why you did so—if there's a good reason then please let the rest of us know.
Mark B
+2  A: 

A small addition to the excellent answers given: If you're running with a non-ajax backup solution for users without javascript, you will have to get those server-side headers correct anyway. This is not impossible, although I understand those that give it up ;)

I'm sure there's another question on SO that will give you the full set of headers that are appropriate. I am not entirely conviced miceus reply covers all the bases 100%.

krosenvold
A: 

Of course "cache-breaking" techniques will get the job done, but this would not happen in the first place if the server indicated to the client that the response should not be cached. In some cases it is beneficial to cache responses, some times not. Let the server decide the correct lifetime of the data. You may want to change it later. Much easier to do from the server than from many different places in your UI code.

Of course this doesn't help if you have no control over the server.

Mark Renouf
+1  A: 

What about using a POST request instead of a GET...? (Which you should anyway...)

Thomas Hansen
I think that's a better solution, but sadly I (somehow) can only do GET request. So.. it's new Date().getTime() for now.
Salamander2007
+4  A: 

JQuery's $.get() will cache the results. Instead of

$.get("myurl", myCallback)

you should use $.ajax, which will allow you to turn caching off:

$.ajax({url: "myurl", success: myCallback, cache: false});
Jonathan Moffatt
+8  A: 

The following will prevent all future AJAX requests from being cached, regardless of which jQuery method you use ($.get, $.ajax, etc.)

$(document).ready(function() {
  $.ajaxSetup({ cache: false });
});
Peter J
Seems like this solution should have at least been voted up so I did :) I just used this solution, and it works for me in IE6. Uses the built-in functionality of jQuery, which makes sense to me if you are using jQuery, as I am. It also seem nice and tidy to me rather than writing more of my own code to generate random numbers. If there is a drawback to this approach that I am missing, feel free to point it out. Otherwise, thanks for pointing that out Peter J!
Carvell Fenton
Upon investigation (Fiddler), it looks like jQuery implements this internally by simply appending a timestamp anyway (as discussed elsewhere in these answers). To me, the .ajaxSetup method is cleaner (in my opinion.)
Peter J
A: 

The real question is why you need this to not be cached. If it should not be cached because it changes all the time, the server should specify to not cache the resource. If it just changes sometimes (because one of the resources it depends on can change), and if the client code has a way of knowing about it, it can append a dummy parameter to the url that is computed from some hash or last modified date of those resources (that's what we do in Microsoft Ajax script resources so they can be cached forever but new versions can still be served as they appear). If the client can't know of changes, the correct way should be for the server to handle HEAD requests properly and tell the client whether to use the cached version or not. Seems to me like appending a random parameter or telling from the client to never cache is wrong because cacheability is a property of the server resource, and so should be decided server-side. Another question to ask oneself is should this resource really be served through GET or should it go through POST? That is a question of semantics, but it also has security implications (there are attacks that work only if the server allows for GET). POST will not get cached.