防止浏览器缓存 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。当$.ajax
和 cache: 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 调用结果的主要内容,如果未能解决你的问题,请参考以下文章