防止浏览器缓存AJAX调用结果


262

看来,如果我使用加载动态内容$.get(),结果将缓存在浏览器中。

在QueryString中添加一些随机字符串似乎可以解决此问题(我使用new Date().toString()),但这听起来像是一种hack。

还有其他方法可以做到这一点吗?或者,如果唯一字符串是实现此目的的唯一方法,则除之外还有其他建议new Date()吗?


您可以使用缩写符号,$.now()而不是每次都使用(new Date()。getTime())。
Dayson 2011年

1
您的问题标题有点误导。您可以考虑重命名吗?
0112年

4
您是否考虑过选择其他答案作为接受答案?
M4N

Answers:


241

我使用new Date().getTime(),这将避免冲突,除非您在同一毫秒内发生多个请求:

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

编辑:这个答案已经好几年了。它仍然有效(因此我没有删除它),但是现在有更好/更干净的方法可以实现此目的。我的首选方法是这种方法,但是如果您要在页面生命周期内为每个请求禁用缓存,答案也很有用。


11
我之所以投票,是因为让jQuery像Peter J的回答那样做更干净。您的解决方案可以工作,但从长远来看更难维护。
尼古拉斯·沃尔夫

11
其中哪一部分需要维护?当与jQuery相比时?
Sunny R Gupta

5
这可能是值得一提的是,new Date().getTime()代码是利用这样的... var nocache = new Date().getTime(); var path = 'http://hostname.domain.tld/api/somejsonapi/?cache=' + nocache;。我花了几分钟才弄清楚,我自己。当然,?cache可能是API实际不需要的任何措辞。
doubleJ

1
即使是Peter J的答案也有+1 的更好解决方案,这也没有错,也不是坏答案。我相信制作DV是因为您的影片高于Peter的影片(被接受)。并且OP自2013年初以来就没有出现在SO上
Michel Ayres

1
url = url + (-1 === url.indexOf('?') ? '?' : '&') + "__=" + Number(new Date());

513

无论您使用哪种jQuery方法($ .get,$。ajax等),以下内容都将防止将来所有AJAX请求都被缓存。

$.ajaxSetup({ cache: false });

7
经调查(Fiddler),看起来jQuery通过简单地附加时间戳(内部在这些答案中其他地方讨论过)在内部实现了此目的。对我而言,.ajaxSetup方法更干净(我认为。)
Peter J 2010年

8
实际上,它不需要在文档就绪调用中。
彼得J

19
为什么要全局禁用ajax缓存?我认为应该像乔纳森(Jonathan)的回答那样,在每次通话的基础上进行。
Sunny R Gupta

5
一切适合您的应用。每当我绝对需要用于所有AJAX调用的新数据时,我都会在商业应用程序中继续使用此方法。对于其他人,缓存的数据很好。
彼得·J

1
链接描述:为将来的Ajax请求设置默认值。不建议使用它。
itwebdeveloper

319

jQuery的$ .get()将缓存结果。代替

$.get("myurl", myCallback)

您应该使用$ .ajax,这将允许您关闭缓存:

$.ajax({url: "myurl", success: myCallback, cache: false});

62
+1这是正确的答案。Peter J的全局禁用缓存的解决方案是IMO的错误做法。
Salman von Abbas

7
重要的是要注意,它只是页面/请求的“全局”。
彼得J

3
+1:缓存应特定于请求类型。某些服务器请求可能很需要缓存(服务器数据是静态的),因此根据请求选择缓存比只关闭所有缓存要好。
Gone Coding

1
+1以获得正确答案-防止使用jQuery的方法而不是手动修改在每次调用的基础上进行缓存。
布伦丹·希尔

2
另一个很好的答案。我不得不说,在大多数情况下,全局禁用缓存具有很大的好处。但这完全取决于您的应用程序的设计方式。没有灵丹妙药,但是在这种情况下,我建议使用一个接受布尔值进行缓存的函数,接受回调的函数以及接受模块化的URL的函数。手动“ hack”很好,但是如果您使用的是jQuery,请尽可能使用其功能。这不仅使现在的开发变得容易,而且将来也可以升级到库。
安东尼·梅森

24

此处的所有答案都在请求的URL上留下足迹,该足迹将显示在服务器的访问日志中。

我需要一个没有副作用的基于标头的解决方案,我发现可以通过设置如何在所有浏览器中控制网页缓存中提到的标头来实现

结果,至少在Chrome上有效,将是:

$.ajax({
   url: url, 
   headers: {
     'Cache-Control': 'no-cache, no-store, must-revalidate', 
     'Pragma': 'no-cache', 
     'Expires': '0'
   }
});


也许是一个愚蠢的问题,但是如果我的Ajax返回图像,图像是否会被缓存?为了避免大量的Amazon S3请求?
MarceloAgimóvel18年

MarceloAgimóvel,我认为这可能是一个单独的SO问题。
艾丁

23

另一种方法是在生成对ajax调用的响应的代码中不从服务器端提供缓存头:

response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );

17
不正确 在IE中,XMLHttpRequest调用将忽略无缓存头,如下所述:stackoverflow.com/questions/244918/…DateTime (或我的.ajaxSetup方法)是唯一有效的解决方案。
彼得·J

我刚刚粘贴了我通常的“无缓存”口头禅,但这并不是说它是IE特定的
miceuz 2010年

2
这应该关闭所有浏览器的缓存:response.setHeader(“ Cache-Control”,“ max-age = 0,no-cache,no-store,post-check = 0,pre-check = 0”);
克里斯·布罗斯基

13

我个人认为查询字符串方法比尝试在服务器上设置标头更可靠-不能保证代理或浏览器无论如何都不会缓存(某些浏览器比其他浏览器差-没有命名)。

我通常使用,Math.random()但使用日期我没有发现任何错误(您不应以足够快的速度进行AJAX请求以两次获得相同的值)。


2
将Date()。getTime()与Math.random()结合在一起,您应该放心。附带说明一下,当指定disableCaching时,Ext.Ajax也使用getTime()。
生动的

12

遵循文档:http : //api.jquery.com/jquery.ajax/

您可以通过以下方式使用该cache属性:

$.ajax({
    method: "GET",
    url: "/Home/AddProduct?",
    data: { param1: value1, param2: value2},
    cache: false,
    success: function (result) {
        // TODO
    }
});

5

当然,“缓存破坏”技术可以完成任务,但是如果服务器向客户端指示不应缓存响应,则不会首先发生这种情况。在某些情况下,缓存响应有时是有益的。让服务器决定数据的正确寿命。您可能以后要更改它。从服务器执行操作比从UI代码中的许多不同位置执行操作容易得多。

当然,如果您无法控制服务器,这将无济于事。


5

如何使用POST请求而不是GET ...?(无论如何,您应该...)


我认为这是一个更好的解决方案,但遗憾的是,我(以某种方式)只能执行GET请求。所以..现在是新的Date()。getTime()。
Salamander2007

请在您的答案中添加一些解释,以便其他人可以从中了解到- 为什么需要POST请求?
Nico Haase

5

真正的问题是,为什么不缓存它?如果不应该因为它一直在更改而对其进行缓存,则服务器应指定不对资源进行缓存。如果它有时只是更改(因为它所依赖的资源之一可能会更改),并且如果客户端代码有一种了解的方式,则可以将伪参数附加到从某个哈希或上次修改日期计算出的url上这些资源(这就是我们在Microsoft Ajax脚本资源中所做的工作,因此可以永久缓存它们,但仍可以按出现的样子提供新版本)。如果客户端不知道更改,则正确的方法应该是服务器正确处理HEAD请求并告诉客户端是否使用缓存的版本。在我看来,像添加随机参数或从客户端告诉永不缓存是错误的,因为可缓存性是服务器资源的属性,因此应在服务器端确定。另一个要问自己的问题是,该资源是应该通过GET真正提供还是应该通过POST提供?这是一个语义问题,但是也有安全隐患(只有在服务器允许GET的情况下,攻击才会起作用)。POST将不会被缓存。


6
如果通过代理服务器而不控制其缓存策略该怎么办?如果您的应用每次明确需要执行新请求怎么办?解决问题的方法并非总是黑白分明,总是有灰色区域。
2011年

是的,这并不总是很明确。但是看到这个答案让我质疑自己的假设,并导致我找到问题的根本原因。可能并非每个人都这样,但这对我有所帮助。如果您在这里阅读本文,也应该考虑一下。
乔纳森·陈

这确实对我有所帮助,ResponseCaching默认设置为60m服务器端。将其更改为“无缓存”,并停止在客户端上缓存。
mattygee

4

也许您应该改用$ .ajax()(如果您使用的是jQuery,看起来像这样)。看一下:http : //docs.jquery.com/Ajax/jQuery.ajax#options和选项“缓存”。

另一种方法是查看如何在服务器端缓存内容。


1
不幸的是,经过一番调查,使用$ .ajax()并设置cache = false基本上会做同样的事情。jQuery将向查询字符串添加一些随机数,并且它不会检查现有的查询字符串。所以我想使用$ .get()就足够了。
Salamander2007

好吧 从未尝试过,只是想起我在文档中看到了一些有关的内容:)
finpingvin

甚至没有必要使用$ .ajax。只需使用.ajaxSetup。
Peter J

3

除了给出的出色答案之外,还有一小部分内容:如果您正在为没有javascript的用户使用非ajax备份解决方案运行,那么无论如何,您都必须正确设置服务器端标头。这不是不可能的,尽管我理解那些放弃的人;)

我确定SO上还有另一个问题,它将为您提供适当的全套标题。我不完全被定罪为胶束答复涵盖所有基础100%。


3

对于那些在移动Safari上使用cache选项的用户$.ajaxSetup(),您似乎必须为POST使用时间戳记,因为移动Safari也会对其进行缓存。根据上的文档$.ajax()(您将从指向$.ajaxSetup()):

将缓存设置为false只能与HEAD和GET请求一起正常使用。它通过在GET参数后面附加“ _ = {timestamp}”来工作。对于其他类型的请求,不需要此参数,但在IE8中,当对GET已请求的URL进行POST时,则不需要该参数。

因此,在我上面提到的情况下,仅设置该选项将无济于事。


2

基本上,只需添加cache:false;ajax,您就认为随着进度的进行内容会发生变化。而内容在那里不会改变的地方,您可以忽略这一点。这样,您每次都会获得新的响应



2

现在,通过在ajax请求中启用/禁用缓存选项很容易做到这一点,就像这样

$(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);
    }
});

3
六年后,您将提供与乔纳森相同的回应?ಠ_ಠ
redent84

人们可以说问题已经发布了6年。我对这个问题的回答与其他任何问题都不同,更不用说它是当今的正确选择。回答此类问题并非针对“问问者”,而是针对社区和初学者!仍然感谢您添加澄清!
Omar El Don

您和这个stackoverflow.com/a/735084/469218和有什么不一样?
redent84 '16

从初学者提出这样的问题的角度来看,也许这很清楚!!
Omar El Don


1

正如@Athasach所说的,根据jQuery文档,$.ajaxSetup({cache:false})除了GET和HEAD请求外,它将不起作用。

Cache-Control: no-cache无论如何,最好还是从服务器发送回标头。它提供了更清晰的关注点分离。

当然,这不适用于您不属于项目的服务URL。在这种情况下,您可以考虑从服务器代码代理第三方服务,而不是从客户端代码调用第三方服务。


1

如果使用的是.net ASP MVC,请通过在端点函数上添加以下属性来禁用对控制器操作的缓存:

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

您能进一步解释吗?该数组与AJAX有什么关系?
Nico Haase

它不是数组,而是MVC Controller Action上的一个属性
马吕斯

0

添加标题

headers: {
                'Cache-Control':'no-cache'
            }

请在您的答案中添加一些解释,以便其他人可以从中学习- 应该在何处添加此类标题?
Nico Haase

-3

附加Math.random() 到请求网址


2
这将导致不稳定的结果。
2014年

Math.random只能用作参数,例如url?_ = [Math.Random()],它与不稳定的结果无关。
xiaoyifang 2014年

4
我知道你在做什么。我只是在评论说Math.Random()有时会给您两次相同的数字。如果您的系统充满不确定性,它们只会彼此叠加。
aj.toulan 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.