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

Posted

技术标签:

【中文标题】防止浏览器缓存 AJAX 调用结果【英文标题】:Prevent browser caching of AJAX call result 【发布时间】:2010-09-26 22:28:36 【问题描述】:

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

在 QueryString 中添加一些随机字符串似乎可以解决这个问题(我使用 new Date().toString()),但这感觉就像一个 hack。

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

【问题讨论】:

您可以使用短符号$.now() 而不是每次都执行 (new Date().getTime())。 您是否考虑过选择另一个答案作为已接受的答案? 【参考方案1】:

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

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

【讨论】:

不正确。在 IE 中,XMLHttpRequest 调用会忽略无缓存标头,如下所述:***.com/questions/244918/… DateTime(或我的 .ajaxSetup 方法)是唯一有效的解决方案。 我刚刚粘贴了我惯用的无缓存口头禅,并没有说明它是特定于 IE 的 这应该关闭所有浏览器的缓存: response.setHeader("Cache-Control", "max-age=0,no-cache,no-store,post-check=0,pre-检查=0");【参考方案2】:

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

我通常使用Math.random(),但我认为使用日期没有任何问题(您不应该以足够快的速度执行 AJAX 请求以两次获得相同的值)。

【讨论】:

将 Date().getTime() 与 Math.random() 结合起来,你应该是安全的。附带说明一下,Ext.Ajax 在指定 disableCaching 时也使用 getTime()。【参考方案3】:

也许你应该看看 $.ajax() 代替(如果你使用的是 jQuery,它看起来像)。 看看:http://docs.jquery.com/Ajax/jQuery.ajax#options 和“缓存”选项。

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

【讨论】:

不幸的是,经过一番调查,使用 $.ajax() 和 set cache = false 基本上会做同样的事情。 jQuery 会在查询字符串中添加一些随机数,并且它不会检查现有的查询字符串。所以我想使用 $.get() 就足够了。 啊,好吧。从来没有尝试过,只是记得我在文档中看到过一些关于它的东西:) 甚至没有必要使用 $.ajax。只需使用 .ajaxSetup。【参考方案4】:

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

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

编辑:这个答案已经有好几年了。它仍然有效(因此我没有删除它),但是现在有更好/更清洁的方法来实现这一点。我更喜欢this 方法,但如果您想在页面的生命周期内为每个 请求禁用缓存,this 答案也很有用。

【讨论】:

我只会投反对票,因为让 jQuery 像 Peter J 的回答那样更简洁。您的解决方案会起作用,但从长远来看更难维护。 其中哪一部分需要维护?与 jQuery 的功能相比? 可能值得注意的是new Date().getTime() 代码是这样使用的...var nocache = new Date().getTime(); var path = 'http://hostname.domain.tld/api/somejsonapi/?cache=' + nocache;。我自己花了几分钟才弄清楚这一点。当然,?cache 可以是 API 实际上不需要的任何措辞。 +1 甚至Peter J's answer 有更好的方法这个答案不是错误的,也不是一个糟糕的答案。我相信制作 DV 是因为您的 DV 高于 Peter 的(已接受)。并且 OP 自 2013 年初以来就没有出现在 SO 上 url = url + (-1 === url.indexOf('?') ? '?' : '&') + "__=" + Number(new Date());【参考方案5】:

对给出的优秀答案的一个小补充:如果您正在为没有 javascript 的用户使用非 ajax 备份解决方案,那么无论如何您都必须正确获取这些服务器端标头。这不是不可能的,虽然我理解那些放弃它的人;)

我确信关于 SO 的另一个问题将为您提供适当的完整标题集。我不完全相信miceus的回复100%涵盖了所有的基础。

【讨论】:

【参考方案6】:

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

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

【讨论】:

【参考方案7】:

使用 POST 请求而不是 GET... 会怎样? (无论如何你应该这样做......)

【讨论】:

我认为这是一个更好的解决方案,但遗憾的是我(不知何故)只能做 GET 请求。所以.. 现在是新的 Date().getTime()。 请在您的答案中添加一些解释,以便其他人可以从中学习 - 为什么需要 POST 请求?【参考方案8】:

JQuery 的 $.get() 将缓存结果。而不是

$.get("myurl", myCallback)

您应该使用 $.ajax,它可以让您关闭缓存:

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

【讨论】:

+1 这是正确答案。 Peter J 的全局禁用缓存解决方案是 IMO 的一种不好的做法。 重要的是要注意它只是页面/请求的“全局”。 +1:缓存应该特定于请求类型。一些服务器请求很可能需要缓存(服务器数据是静态的),因此在逐个请求的基础上选择缓存比仅仅全部关闭要好。跨度> 另一个很好的答案。我不得不说,对我来说,大多数时候全局禁用缓存是非常有益的。这完全取决于您的应用程序是如何设计的。没有灵丹妙药,但在这种情况下,我会推荐一个函数,该函数接受一个用于缓存的布尔值、一个用于回调的函数和一个用于模块化的 URL。手动“hack”很好,但如果您使用的是 jQuery,请尽可能坚持使用它们的功能。这不仅会使现在的开发变得更容易,而且将来也可以对库进行升级。 “JQuery 的 $.get() 将缓存结果”并非完全正确;可能决定使用缓存结果的是浏览器,而不是 jQuery。当 $.ajaxcache: false 一起使用时,jQuery 会将时间戳附加到 URL,以确保来自服务器的新响应。【参考方案9】:

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

$.ajaxSetup( cache: false );

【讨论】:

经过调查(提琴手),看起来 jQuery 通过简单地附加时间戳在内部实现了这一点(如这些答案中其他地方所讨论的)。对我来说,.ajaxSetup 方法更干净(在我看来)。 确实不需要在文档就绪调用中。 为什么要全局禁用ajax缓存?我认为应该按照每次通话来完成,就像乔纳森的回答一样。 适用于您的应用程序。每当我绝对需要所有 AJAX 调用的新数据时,我都会继续在商业应用程序中使用这种方法。对于其他人来说,缓存数据很好。 link 描述:为未来的 Ajax 请求设置默认值。不推荐使用它。【参考方案10】:

真正的问题是为什么你需要这个不被缓存。如果它不应该被缓存,因为它一直在变化,服务器应该指定不缓存资源。如果它有时只是改变(因为它所依赖的资源之一可以改变),并且如果客户端代码有办法知道它,它可以将一个虚拟参数附加到从某个哈希或上次修改日期计算的 url这些资源的一部分(这就是我们在 Microsoft Ajax 脚本资源中所做的,因此它们可以被永久缓存,但新版本仍然可以在它们出现时提供)。如果客户端不知道变化,正确的方法应该是服务器正确处理 HEAD 请求并告诉客户端是否使用缓存版本。 在我看来,附加一个随机参数或告诉客户端永远不要缓存是错误的,因为可缓存性是服务器资源的属性,因此应该在服务器端决定。 另一个要问自己的问题是,该资源真的应该通过 GET 提供还是应该通过 POST 提供?这是一个语义问题,但它也有安全隐患(只有在服务器允许 GET 时才会发生攻击)。 POST 不会被缓存。

【讨论】:

如果您正在使用无法控制其缓存策略的代理服务器怎么办?如果您的应用每次都明确需要执行新请求怎么办?事情的答案并不总是黑白分明,总有灰色地带。 没错,这并不总是一目了然。但是看到这个答案让我质疑我的假设,并让我找到了问题的根本原因。可能不是每个人都这样,但它帮助了我。如果您正在阅读本文,您也应该考虑一下。 这对我有帮助,ResponseCaching 默认设置为 60m 服务器端。将其更改为 No-Cache 并停止在客户端缓存。【参考方案11】:

如果您使用的是 IE 9,那么您需要在控制器类定义前使用以下内容:

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

公共类 TestController : 控制器

这将阻止浏览器缓存。

此链接的详细信息: http://dougwilsonsa.wordpress.com/2011/04/29/disabling-ie9-ajax-response-caching-asp-net-mvc-3-jquery/

其实这解决了我的问题。

【讨论】:

【参考方案12】:

对于那些在移动 Safari 上使用 $.ajaxSetup()cache 选项的人来说,您可能必须为 POST 使用时间戳,因为移动 Safari 也会缓存它。根据$.ajax() 上的文档(您是从$.ajaxSetup() 定向到的):

将缓存设置为 false 仅适用于 HEAD 和 GET 请求。它通过将“_=timestamp”附加到 GET 参数来工作。其他类型的请求不需要该参数,除非在 IE8 中对已由 GET 请求的 URL 进行 POST。

因此,在我上面提到的情况下,单独设置该选项对您没有帮助。

【讨论】:

【参考方案13】:

正如@Athasach 所说,根据 jQuery 文档,$.ajaxSetup(cache:false) 不适用于 GET 和 HEAD 请求。

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

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

【讨论】:

【参考方案14】:

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

【讨论】:

这会给出不稳定的结果。 Math.random 只会作为参数,和url?_=[Math.Random()] 一样,与不稳定的结果无关。 我明白你在做什么。我只是在评论 Math.Random() 有时会给你两次相同的数字。如果你的系统充满了不确定性,它们只会叠加在一起。【参考方案15】:

基本上只需在 ajax 中添加cache:false;,您认为内容会随着进度的进行而改变。并且内容不会改变的地方你可以省略它。这样你每次都会得到新的响应

【讨论】:

【参考方案16】:

Internet Explorer’s Ajax Caching: What Are YOU Going To Do About It? 建议三种方法:

    向查询字符串添加缓存破坏标记,例如 ?date=[timestamp]。在 jQuery 和 YUI 中,您可以告诉它们自动执行此操作。 使用 POST 而不是 GET 发送一个 HTTP 响应头,专门禁止浏览器缓存它

【讨论】:

【参考方案17】:

按照文档: http://api.jquery.com/jquery.ajax/

您可以将cache 属性用于:

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

【讨论】:

【参考方案18】:

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

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

【讨论】:

您能进一步解释一下吗?该数组与 AJAX 有何关系? 它不是一个数组,它是一个 MVC 控制器操作上的 attribute。【参考方案19】:

现在,通过在 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);
    
);

【讨论】:

6 年后,您提供的回复与乔纳森一样吗? ಠ_ಠ 人们可以看出问题发布后的 6 年。我对这个问题的回答与其他任何人都不一样,更不用说它是当今正确的答案。回答这些问题不是为了“提问者”,而是为了社区和初学者!无论如何,感谢您添加说明! 你的和***.com/a/735084/469218这个有什么区别? 也许是清晰,从初学者的角度提出这样的问题!【参考方案20】:

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

我需要一个没有副作用的基于标头的解决方案,我发现可以通过设置How to control web page caching, across all browsers? 中提到的标头来实现。

至少适用于 Chrome 的结果是:

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

【讨论】:

也许是个愚蠢的问题,但是如果我的 ajax 返回图像,图像会被缓存吗?避免大量 Amazon S3 请求? MarceloAgimóvel,我相信这可能是一个单独的 SO 问题。【参考方案21】:

添加标题

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

【讨论】:

请在您的答案中添加一些解释,以便其他人可以从中学习 - 在哪里应该添加这样的标题?

以上是关于防止浏览器缓存 AJAX 调用结果的主要内容,如果未能解决你的问题,请参考以下文章

Internet Explorer 缓存 asp.net mvc ajax 结果

ajax请求请求数据缓存问题分析以及解决方案

防止图像文件被添加到浏览器缓存

IE浏览器关于ajax的缓存机制

MVC中使用jquery的浏览器缓存问题

ajax缓存