276

It looks like if I load dynamic content using $.get(), the result is cached in browser.

Adding some random string in QueryString seems 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()?

sideshowbarker
  • 62,215
  • 21
  • 143
  • 153
Salamander2007
  • 5,974
  • 8
  • 30
  • 26

21 Answers21

532

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

$.ajaxSetup({ cache: false });
Peter J
  • 55,560
  • 7
  • 36
  • 45
  • 7
    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 Jan 29 '10 at 22:33
  • Why does this need to be inside the document ready call? How can I be sure that none of my other document ready handlers (with ajax calls) will fire before this one? – Michiel Cornille Jun 28 '11 at 15:29
  • 8
    Indeed it does not need to be inside the document ready call. – Peter J Jul 15 '11 at 21:14
  • where do we need to place this piece of code? And do we need to place this in every page that calls $.ajax ? – Niar Feb 16 '13 at 08:15
  • Place the code so it is called once on page load, before any $.ajax call. – Peter J Feb 16 '13 at 19:40
  • 20
    Why disable ajax caching globally? I think it should be done on a per call basis, like what Jonathan's answer does. – Sunny R Gupta May 30 '13 at 09:03
  • You are correct. If you want to control caching for each request separately instead of globally for all requests on a page, go for it! – Peter J May 30 '13 at 18:48
  • This answer works great for me. But i have one doubt, i have many javascript functions in same jsp page, each function will internally make ajax call. So do i need to write code in your answer in all the functions? – Kishan_KP Jul 14 '13 at 09:58
  • No, once on page load. – Peter J Jul 14 '13 at 20:55
  • 6
    Whatever works for your app. I continue to use this method in commercial apps whenever I absolutely need fresh data for all AJAX calls. For others, cached data is fine. – Peter J Sep 05 '13 at 19:46
  • On one hand, Peter is right. On another hand, a downside with this approach is that some junior dev or horrible senior dev may end up burning a lot of time trying to figure out why their call is being cache; and not realize it is being set global. Extra bad, they may end up using a global setter to set another global setter, thinking it is the way to do it. Playing with global variable is like gas dancing near fire. – Phil Feb 07 '14 at 21:32
  • jQuery's AJAX object will follow redirects, so even if you disable caching globally the `"_={timestamp}"` parameter that jQuery adds to bust the browser's cache may not be forwarded with the redirect. In that case, your request can still be cached by the browser. The solution is to either make sure that special param is passed along with redirects, or you disable caching in the server-side code for those requests. (Example, https://gist.github.com/chrisbloom7/a879915f7921a3ca11c3#file-application_controller-rb) – Chris Bloom Sep 09 '14 at 14:57
  • 1
    [link](https://api.jquery.com/jquery.ajaxsetup/) Description: Set default values for future Ajax requests. Its use is not recommended. – itwebdeveloper Aug 11 '15 at 16:11
  • 1
    If you are worried about impacting caching static content, jQuery doesn't prevent it unless you are explicitly loading scripts and styles via a $.get or the like. If you are working with partial views, ajax gets and the like, I strongly suggest you implement this solution, otherwise things can get hairy. I find it easiest to dump this on a layout/master page so there is no redundancy. – Anthony Mason May 23 '16 at 13:46
  • UC browser seems to doesn't understand this option I guess. – The_ehT Aug 11 '16 at 13:51
343

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
  • 12,501
  • 6
  • 46
  • 48
  • 69
    +1 This is the correct answer. Peter J's solution of globally disabling caching is a bad practice IMO. – Salman von Abbas Apr 19 '12 at 13:48
  • 8
    Important to note that it's only "global" for the page / request. – Peter J May 09 '12 at 15:39
  • 3
    +1: Caching should be specific to the request type. Some server requests may well need caching (where the server data is static), so choosing caching on a *request by request* basis is better than just *turning it all off*. – Gone Coding Sep 04 '13 at 16:07
  • 1
    +1 for correct answer - preventing caching on a per-call basis using jQuery's method, rather than a manual hack. – Brendan Hill Jan 16 '14 at 23:02
  • 2
    Another good answer. I have to say, for me, most of the time globally disabling the cache has been of great benefit. It all depends on how your application is designed though. There is no silver bullet, but in this situation, I would recommend a function that accepts a boolean for caching, function for callback, and URL for modularity. The manual "hack" is fine, but if you are using jQuery, stick to their functions whenever possible. This will not only make development easier now, but future upgrades to the library as well. – Anthony Mason May 23 '16 at 13:50
  • 3
    "JQuery's $.get() will cache the results" isn't strictly true; it's the browser that may decide to use the cached result, not jQuery. When using `$.ajax` with `cache: false` jQuery appends the timestamp to the URL, which ensures a fresh response from the server. – DigitalDan Jan 02 '18 at 16:59
  • 1
    The best answer, imo. As an example, suppose you need to make a series of ajax calls to the same url (e.g., a connector). In most cases, only the first one should to be made with the cache disabled. – Bob Ray Sep 24 '18 at 15:49
248

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

$.get('/getdata?_=' + new Date().getTime(), function(data) {
    console.log(data); 
});

Edit: This answer is several years old. It still works (hence I haven't deleted it), but there are better/cleaner ways of achieving this now. My preference is for this method, but this answer is also useful if you want to disable caching for every request during the lifetime of a page.

Community
  • 1
  • 1
Mark Bell
  • 27,184
  • 22
  • 109
  • 138
  • 15
    I will downvote only because it's cleaner to let jQuery do this as in the answer by Peter J. Your solution will work, but is more difficult to maintain in the long run. – Niklas Wulff Jan 13 '11 at 12:46
  • 13
    What part of this requires maintenance? When compared to what jQuery does? – Sunny R Gupta May 30 '13 at 09:02
  • 5
    It may be worth noting that the `new Date().getTime()` code is utilized like this...`var nocache = new Date().getTime(); var path = 'http://hostname.domain.tld/api/somejsonapi/?cache=' + nocache;`. It took me a few minutes to figure that one out, myself. Of course `?cache` could be any wording that the API doesn't actually want. – doubleJ Jul 10 '13 at 04:15
  • 1
    +1 even [Peter J's answer](http://stackoverflow.com/a/735101/662581) having a better approach this answer isn't wrong nor is a bad answer. I believe that the DV are made because yours is above Peter's (as accepted). and the OP doesn't appear on SO since early 2013 – Michel Ayres Sep 05 '14 at 13:01
  • 1
    `url = url + (-1 === url.indexOf('?') ? '?' : '&') + "__=" + Number(new Date());` –  Feb 23 '15 at 11:58
  • This is the only way worked for me.. in FF.. Great technique. thanx – Girish Thimmegowda Oct 04 '15 at 10:31
  • @salamander2007 This shouldn't be the accepted answer, `cache: false` is the correct approach in JQuery. – user692942 Jul 20 '20 at 08:30
  • jQuery's `cache: false` does exactly the same thing, i.e., appends a `_={{timestamp}}` GET parameter to the request: https://api.jquery.com/jquery.ajax/ Instead of the jQuery magic behind the scene, this answer is more explicit. – onurmatik May 18 '21 at 09:03
24

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
  • 3,233
  • 4
  • 27
  • 33
  • 17
    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-once The DateTime (or my .ajaxSetup method) are the only solutions that actually work. – Peter J Jan 29 '10 at 22:35
  • i've just pasted my usual no cache mantra, it's not stated that it's IE specific – miceuz Feb 01 '10 at 11:46
  • 2
    This should shut off caching for all browsers: response.setHeader("Cache-Control", "max-age=0,no-cache,no-store,post-check=0,pre-check=0"); – Chris Broski Apr 15 '15 at 17:22
24

All the answers here leave a footprint on the requested URL which will show up in the access logs of server.

I needed a header based solution with no side effect and I found it can be achieved by setting up the headers mentioned in How to control web page caching, across all browsers?.

The result, working for Chrome at least, would be:

$.ajax({
   url: url, 
   headers: {
     'Cache-Control': 'no-cache, no-store, must-revalidate', 
     'Pragma': 'no-cache', 
     'Expires': '0'
   }
});
Aidin
  • 7,505
  • 2
  • 35
  • 33
14

Following the documentation: http://api.jquery.com/jquery.ajax/

you can use the cache property with:

$.ajax({
    method: "GET",
    url: "/Home/AddProduct?",
    data: { param1: value1, param2: value2},
    cache: false,
    success: function (result) {
        // TODO
    }
});
Mark Bell
  • 27,184
  • 22
  • 109
  • 138
MrMins
  • 9,633
  • 10
  • 67
  • 127
14

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
  • 295,929
  • 52
  • 357
  • 326
  • 2
    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 Dec 15 '08 at 09:53
6

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
  • 29,573
  • 19
  • 89
  • 120
6

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.

  • 7
    What if you are going through proxy servers that you don't control their caching policy? what if your app explicitly needs to do a new request every time? The answer to things are not always clear cut black and white, there are always gray areas. – 7wp Mar 31 '11 at 04:36
  • True, it's not always clear cut. But seeing this answer made me question my assumptions and led me to find the root cause of my problem. That may not be the case for everyone, but it helped me. If you're here reading this, you should consider it also. – Jonathan Tran Aug 16 '16 at 22:05
  • This did help me, ResponseCaching was set to 60m server side by default. Changed it to No-Cache and it stopped caching on the client. – mattygee Mar 17 '20 at 16:09
5

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
  • 664
  • 1
  • 7
  • 13
  • 1
    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 Dec 15 '08 at 09:33
  • Ah okey. Never tried it, just remembered i'd seen something about it in the docs :) – finpingvin Dec 15 '08 at 09:59
  • It's not even necessary to use $.ajax. Simply use .ajaxSetup. – Peter J Apr 09 '09 at 17:12
5

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

Thomas Hansen
  • 5,443
  • 1
  • 21
  • 28
  • 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 Dec 16 '08 at 00:46
  • 1
    Please add some explanation to your answer such that others can learn from it - **why** should a POST request be needed? – Nico Haase Apr 30 '20 at 15:44
4

For those of you using the cache option of $.ajaxSetup() on mobile Safari, it appears that you may have to use a timestamp for POSTs, since mobile Safari caches that too. According to the documentation on $.ajax() (which you are directed to from $.ajaxSetup()):

Setting cache to false will only work correctly with HEAD and GET requests. It works by appending "_={timestamp}" to the GET parameters. The parameter is not needed for other types of requests, except in IE8 when a POST is made to a URL that has already been requested by a GET.

So setting that option alone won't help you in the case I mentioned above.

Athasach
  • 43
  • 5
3

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
  • 70,511
  • 27
  • 141
  • 205
2

Basically just add cache:false; in the ajax where you think the content will change as the progress go on. And the place where the content wont change there u can omit this. In this way u will get the new response every time

2

Internet Explorer’s Ajax Caching: What Are YOU Going To Do About It? suggests three approaches:

  1. Add a cache busting token to the query string, like ?date=[timestamp]. In jQuery and YUI you can tell them to do this automatically.
  2. Use POST instead of a GET
  3. Send a HTTP response header that specifically forbids browsers to cache it
LCJ
  • 20,854
  • 59
  • 228
  • 387
1

As @Athasach said, according to the jQuery docs, $.ajaxSetup({cache:false}) will not work for other than GET and HEAD requests.

You are better off sending back a Cache-Control: no-cache header from your server anyway. It provides a cleaner separation of concerns.

Of course, this would not work for service urls that you do not belong to your project. In that case, you might consider proxying the third party service from server code rather than calling it from client code.

rstackhouse
  • 1,871
  • 19
  • 24
1

If you are using .net ASP MVC, disable the caching on the controller action by adding the following attribute on the end point function:

[OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]
noam621
  • 2,518
  • 1
  • 13
  • 24
Marius
  • 75
  • 6
  • Can you explain that further? How does that array relate to AJAX? – Nico Haase Apr 30 '20 at 15:43
  • It's not an array, its an [attribute](https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.outputcacheattribute?view=aspnet-mvc-5.2) on a MVC Controller Action. – Marius May 02 '20 at 08:39
1

Now, it's easy to do it by enabling/disabling cache option in your ajax request, just like this

$(function () {
    var url = 'your url goes here';
    $('#ajaxButton').click(function (e) {
        $.ajax({
            url: url,
            data: {
                test: 'value'
            },
                cache: true, //cache enabled, false to reverse
                complete: doSomething
            });
        });
    });
    //ToDo after ajax call finishes
    function doSomething(data) {
        console.log(data);
    }
});
Mark Bell
  • 27,184
  • 22
  • 109
  • 138
El Don
  • 792
  • 5
  • 14
  • 4
    After 6 years you're providing the same response that Jonathan? ಠ_ಠ – redent84 Feb 26 '16 at 14:21
  • people can tell it's 6 years after the question is posted. And my answer to that question is different from any one else, not to mention it is the a correct one nowadays. Answering such questions is not for the "asker" it's for the community and beginners! Thanks for adding the clarification anyway! – El Don Feb 26 '16 at 23:20
  • 1
    And what's the difference between yours and this one http://stackoverflow.com/a/735084/469218? – redent84 Feb 28 '16 at 17:37
  • maybe it is clarity, from the point of view of a beginner asking such a question!! – El Don Feb 28 '16 at 19:49
0

If you are using IE 9, then you need to use the following in front of your controller class definition:

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]

public class TestController : Controller

This will prevent the browser from caching.

Details on this link: http://dougwilsonsa.wordpress.com/2011/04/29/disabling-ie9-ajax-response-caching-asp-net-mvc-3-jquery/

Actually this solved my issue.

Net Solver
  • 127
  • 1
  • 7
0

add header

headers: {
                'Cache-Control':'no-cache'
            }
Moaz Salem
  • 440
  • 2
  • 5
  • Please add some explanation to your answer such that others can learn from it - **where** should such headers be added? – Nico Haase Apr 30 '20 at 15:43
-2

append Math.random() to the request url

noam621
  • 2,518
  • 1
  • 13
  • 24
xiaoyifang
  • 810
  • 10
  • 12
  • 3
    This will give unstable results. – aj.toulan Apr 09 '14 at 14:46
  • Math.random will only act as a prameter,like url?_=[Math.Random()],it has nothing to do with unstable result. – xiaoyifang Apr 10 '14 at 10:01
  • 5
    I understand what you were doing. I was merely commenting that Math.Random() will sometimes give you the same number twice. If you fill your system with uncertainties, they will only add on top of one another. – aj.toulan Apr 10 '14 at 18:07