在 IE8 中意外缓存 AJAX 结果

Posted

技术标签:

【中文标题】在 IE8 中意外缓存 AJAX 结果【英文标题】:Unexpected Caching of AJAX results in IE8 【发布时间】:2010-11-04 01:25:57 【问题描述】:

我在 Internet Explorer 缓存来自 JQuery Ajax 请求的结果方面遇到了严重问题。

我的网页上有标题,每次用户导航到新页面时都会更新。加载页面后,我会这样做

$.get("/game/getpuzzleinfo", null, function(data, status) 
    var content = "<h1>Wikipedia Maze</h1>";
    content += "<p class='endtopic'>Looking for <span><a title='Opens the topic you are looking for in a separate tab or window' href='" + data.EndTopicUrl + "' target='_blank'>" + data.EndTopic + "<a/></span></p>";
    content += "<p class='step'>Step <span>" + data.StepCount + "</span></p>";
    content += "<p class='level'>Level <span>" + data.PuzzleLevel.toString() + "</span></p>";
    content += "<p class='startover'><a href='/game/start/" + data.PuzzleId.toString() + "'>Start Over</a></p>";

    $("#wikiheader").append(content);

, "json");

它只是将标题信息注入页面。你可以去www.wikipediamaze.com查看它,然后登录并开始一个新的谜题。

在我测试过的所有浏览器(Google Chrome、Firefox、Safari、Internet Explorer)中,它在 IE 中除了都运行良好。 第一次在 IE 中注入的一切都很好,但之后它甚至从未调用过 /game/getpuzzleinfo。好像它已经缓存了结果什么的。

如果我将呼叫更改为$.post("/game/getpuzzleinfo", ... IE 会很好地接听它。但随后 Firefox 停止工作。

有人可以解释一下为什么 IE 会缓存我的 $.get ajax 调用吗?

更新

根据下面的建议,我已将我的 ajax 请求更改为此,这解决了我的问题:

$.ajax(
    type: "GET",
    url: "/game/getpuzzleinfo",
    dataType: "json",
    cache: false,
    success: function(data)  ... 
);

【问题讨论】:

感谢您提出这个问题。我对这种浏览器行为感到无语。 好问题,非常酷的网站。好主意。 【参考方案1】:

IE 因其积极缓存 Ajax 响应而臭名昭著。当您使用 jQuery 时,您可以设置一个全局选项:

$.ajaxSetup(
    cache: false
);

这将导致 jQuery 向请求查询字符串添加一个随机值,从而防止 IE 缓存响应。

请注意,如果您确实需要缓存的地方还有其他 Ajax 调用,这也会为这些调用禁用它。在这种情况下,切换到使用 $.ajax() 方法并为必要的请求显式启用该选项。

请参阅http://docs.jquery.com/Ajax/jQuery.ajaxSetup 了解更多信息。

【讨论】:

您还可以在网址末尾添加时间戳。不知道为什么 jQuery 不采用这种方法。 @Eric:这就是 jQuery 在内部所做的——“cache: false”选项只是告诉它这样做。 为什么 jquery 默认不开启这个? 我刚刚注意到,当您尝试在 IE 8 中通过调用 / 请求主页时,缓存选项不起作用。将其更改为 /index.php 或任何完整的 url。或者自己添加一些假参数,例如/?f=f【参考方案2】:

正如marr75 提到的,GET 被缓存。

有几种方法可以解决这个问题。除了修改响应标头之外,您还可以将随机生成的查询字符串变量附加到目标 URL 的末尾。这样,IE每次请求时都会认为是不同的URL。

有多种方法可以做到这一点(例如使用Math.random()、更改日期等)。

这是一种方法:

var oDate = new Date();
var sURL = "/game/getpuzzleinfo?randomSeed=" + oDate.getMilliseconds();
$.get(sURL, null, function(data, status) 
    // your work
);

【讨论】:

【参考方案3】:

获取总是可缓存的。一种可行的策略是编辑响应标头并告诉客户端不要缓存信息或尽快使缓存过期。

【讨论】:

这听起来是个好主意。我该怎么做呢? 这是一个加载问题,取决于您的服务器端代码。请参阅***条目“HTTP 标头列表”以获得一些指导。示例: Cache-Control: no-cache Expires: Thu, 01 Dec 1994 16:00:00 GMT 基本上您需要将这些响应标头附加到您的 http 响应中。它在 ASP.NET、Ruby 和 PHP 中相当简单。只需查找您正在使用的服务器端语言 + 修改响应标头。 另外,这根本不是对 Jquery 的批评(我喜欢那个库),添加随机查询字符串参数的方法是安全的,但对客户端来说是不礼貌的(它会让他们坚持缓存中永远不会再次使用的项目)。【参考方案4】:

如果您正在调用 ashx 页面,您还可以使用以下代码禁用服务器上的缓存:

context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches); 

【讨论】:

【参考方案5】:

这就是我为 ajax 调用所做的:

var url = "/mypage.aspx";
// my other vars i want to add go here
url = url + "&sid=" + Math.random();
// make ajax call

对我来说效果很好。

【讨论】:

【参考方案6】:

NickFitz 给出了一个很好的答案,但是您还需要在 IE9 中关闭缓存。为了只针对 IE8 和 IE9,您可以这样做;

<!--[if lte IE 9]>
<script>
    $.ajaxSetup(
        cache: false
    );
</script>
<![endif]-->

【讨论】:

【参考方案7】:

这里的答案对于那些使用 jQuery 或者出于某种原因直接使用 xmlHttpRequest 对象的人非常有帮助...

如果您使用的是自动生成的 Microsoft 服务代理,则解决起来并不简单。

诀窍是在事件处理程序中使用 Sys.Net.WebRequestManager.add_invokingRequest 方法更改请求 url:

networkRequestEventArgs._webRequest._url = networkRequestEventArgs._webRequest._url + '&nocache=' + new Date().getMilliseconds(); 

我在博客上写过这个:http://yoavniran.wordpress.com/2010/04/27/ie-caching-ajax-results-how-to-fix/

【讨论】:

【参考方案8】:

刚刚写了一篇关于这个确切问题的博客,只使用 ExtJS (http://thecodeabode.blogspot.com/2010/10/cache-busting-ajax-requests-in-ie.html )

问题是因为我使用的是特定的 url 重写格式,所以我不能使用常规的查询字符串参数 (?param=value),所以我将缓存破坏参数写为发布的变量.....我本来会认为使用 POST 变量比 GET 更安全,仅仅是因为很多 MVC 框架都使用该模式

protocol://host/controller/action/param1/param2

所以变量名到值的映射丢失了,参数被简单地堆叠了......所以当使用 GET 缓存破坏器参数时

即协议://host/controller/action/param1/param2/no_cache122300201

no_cache122300201 可能被误认为是具有默认值的 $param3 参数

公共函数动作($param1, $param2, $param3 = "默认值") //..//

POSTED 缓存破坏者不会发生这种情况

【讨论】:

【参考方案9】:

如果您使用的是 ASP.NET MVC,只需在控制器操作顶部添加这一行即可:

[OutputCache(NoStore=true, Duration = 0, VaryByParam = "None")]
public ActionResult getSomething()



【讨论】:

有问题的行为在浏览器端;这个答案与服务器端的缓存有关。 @MarkSowul Outputcache 有 3 个选项 Client、Server 和 any。 IE 使用 OutputCache 作为默认值,它主要用作客户端缓存。您可以在这里查看更多详细信息dougwilsonsa.wordpress.com/2011/04/29/… @MarkSowul 您也可以在此处查看相关问题和答案。你认为这也在服务器端吗? ***.com/questions/2653092/… 是的,抱歉,您是对的——我没有意识到您的回答会影响服务器端缓存和客户端缓存。跨度> 【参考方案10】:

IE 有权进行此缓存;为确保项目不被缓存,应相应地设置标题。

如果你使用的是ASP.NET MVC,你可以写一个ActionFilter;在OnResultExecuted,检查filterContext.HttpContext.Request.IsAjaxRequest()。如果是这样,设置响应的过期标头:filterContext.HttpContext.Response.Expires = -1;

根据http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/:

有些人更喜欢使用 Cache - Control: no - 缓存头 而不是过期。区别如下: Cache-Control:no-cache – 绝对没有缓存 Expires:-1 – 浏览器“通常”联系 用于通过条件更新该页面的 Web 服务器 If-Modified-Since 请求。但是,该页面仍保留在磁盘缓存中 并在适当的情况下使用而无需联系遥控器 Web 服务器,例如当 BACK 和 FORWARD 按钮用于 访问导航历史记录或浏览器处于离线模式时。

【讨论】:

以上是关于在 IE8 中意外缓存 AJAX 结果的主要内容,如果未能解决你的问题,请参考以下文章

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

ajax缓存

Internet Explorer 缓存 asp.net mvc ajax 结果

显示来自 localStorage 缓存的数据,然后使用来自服务的 AJAX 结果进行更新

jQuery AJAX GET html 数据 IE8 不工作

IE 8 和客户端缓存