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

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

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

有没有其他方法来实现这一点? 或者,如果唯一字符串是实现这一点的唯一方法,除了new Date()还有其他建议吗?< / p >

336543 次浏览

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

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

我个人觉得查询字符串方法比试图在服务器上设置头文件更可靠——不能保证代理或浏览器不会缓存它(有些浏览器比其他浏览器更差——没有命名)。

我通常使用Math.random(),但我不认为使用日期有任何错误(你不应该做AJAX请求足够快,以获得相同的值两次)。

也许你应该看看$.ajax()而不是(如果你使用的是jQuery,它看起来像)。 看一下:http://docs.jquery.com/Ajax/jQuery.ajax#options和选项"cache".

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

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

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

这个答案是几年前的了。它仍然可以工作(因此我没有删除它),但是现在有更好/更干净的方法来实现这一点. c。我的首选是方法,但如果你想在页面的生命周期内禁用每一个请求的缓存,答案也很有用。

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

我相信还有另一个关于SO的问题会给你全套合适的标题。我不完全相信老鼠的回答涵盖了所有的基础100%。

当然,“缓存破坏”技术可以完成这项工作,但是如果服务器指示客户机不应该缓存响应,那么这种情况一开始就不会发生。在某些情况下缓存响应是有益的,而在某些情况下则不然。让服务器决定数据的正确生命周期。稍后您可能想要更改它。在服务器上比在UI代码的其他地方要容易得多。

当然,如果您无法控制服务器,这是没有帮助的。

用POST请求代替GET请求怎么样? (无论如何你应该…)

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

$.get("myurl", myCallback)

你应该使用$。Ajax,它将允许你关闭缓存:

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

下面的代码将阻止所有将来的AJAX请求被缓存,无论您使用的是哪种jQuery方法($。,美元。ajax,等等)。

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

如果你正在使用ie9,那么你需要在你的控制器类定义前使用以下代码:

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

公共类TestController:控制器

这将阻止浏览器缓存。

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

实际上这解决了我的问题。

对于那些在移动Safari上使用$.ajaxSetup()cache选项的人来说,似乎你必须为post使用时间戳,因为移动Safari也会缓存它。根据$.ajax()上的文档(你会被引导到$.ajaxSetup()):

将cache设置为false将只对HEAD和GET请求有效。它通过将“_={timestamp}”附加到GET参数来工作。对于其他类型的请求,该参数不需要,除非在IE8中,当对一个已经被GET请求的URL进行POST时。

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

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

不管怎样,你最好从服务器返回Cache-Control: no-cache报头。它提供了更清晰的关注点分离。

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

Math.random()附加到请求url

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

Internet Explorer的Ajax缓存:你打算怎么做?建议三种方法:

  1. 在查询字符串中添加一个缓存破坏令牌,比如?date=[timestamp]。在jQuery和YUI中,您可以告诉它们自动执行此操作。
  2. 使用POST而不是GET
  3. 发送一个HTTP响应头,明确禁止浏览器缓存它

以下文档: http://api.jquery.com/jquery.ajax/ < / p >

你可以使用cache属性:

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

如果你正在使用。net ASP MVC,通过在end point函数上添加以下属性禁用控制器动作上的缓存:

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

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

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

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

结果是,至少在Chrome上是这样的:

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

添加标题

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