jQuery ajax ifModified在调用缓存响应时没有荣幸,应该是304

Lee*_*eco 2 ajax jquery caching google-chrome http-status-code-304

我正在使用jQuery ajax从ASP.Net MVC应用程序中检索json,并且在进行ajax调用时我没有看到预期的结果ifModified = true.

我正在使用jQuery 1.9.1和Chrome版本26.0.1410.64 m

当使用新的浏览器实例并对已经缓存的内容进行初始请求时,即使在ajax配置中设置了ifModified = true,也不会调用服务器来检查缓存状态.在来自同一浏览器实例的后续请求中,(预期)对服务器进行调用,服务器以304响应.

在初始请求中,浏览器网络跟踪显示内容是从状态为200的缓存传递的,即使从未检查过修改日期.Fiddler没有显示任何请求,并且ASP.Net MVC控制器中的断点未被命中.

这是一个错误,还是有办法让它正常工作?如果它是一个错误,它是一个jQuery错误还是Chrome错误?

这是一个简化的ajax调用:

var req = $.ajax({
    type: "GET",
    dataType: "json",
    url: "/JsonTest/GetJson",
    ifModified: true,
    success: function (data, status, jqXHR) {
        if (data === undefined && status == "notmodified") {
            $.ajax({
                type: this.type,
                dataType: this.dataType,
                url: this.url,
                ifModified: false,
                success: this.success,
                error: this.error,
                complete: this.complete
            });
        } else {
            alert($.toJSON(data));
        }
    },
    error: function (jqXHR, status, error) {
        alert(error);
    },
    complete: function (jqXHR, status) {
    }
});
Run Code Online (Sandbox Code Playgroud)

这是一个简化的ASP.Net MVC控制器方法:

[AllowAnonymous]
public ActionResult GetJson()
{
    // dummy data version.
    var currentVersion = new DateTime(2013, 04, 30, 12, 0, 0);

    // get client cached version from request
    DateTime cachedVersion;
    if (DateTime.TryParseExact(HttpContext.Request.Headers["If-Modified-Since"], "r", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out cachedVersion))
    {
        cachedVersion = cachedVersion.ToLocalTime();
    }
    else
    {
        cachedVersion = DateTime.MinValue;
    }

    // return 304 if not changed
    if (currentVersion.Subtract(cachedVersion).Duration() < TimeSpan.FromSeconds(1))
    {
        HttpContext.Response.StatusCode = 304;
        HttpContext.Response.StatusDescription = "Not Modified";
        return new EmptyResult();
    }

    // still here? return current object and set current version response header
    var rv = new { name = "Hello", value = "World" };
    HttpContext.Response.Cache.SetCacheability(HttpCacheability.Private);
    HttpContext.Response.Cache.SetLastModified(currentVersion);
    return Json(rv, JsonRequestBehavior.AllowGet);
}
Run Code Online (Sandbox Code Playgroud)

重现的步骤:1)启动新的浏览器实例2)启动ajax请求3)关闭响应警报窗口4)启动ajax请求5)关闭浏览器重复

第一次通过,空缓存:第2步向服务器发出请求.服务器以200.步骤4发出请求响应服务器,服务器响应304.

第二次通过 - 缓存中的响应:步骤2不向服务器发出请求.响应来自具有200状态的缓存.步骤4向服务器发出请求,服务器响应304.

我希望第二次通过步骤#2向服务器发出请求并接收304.

每次使用缓存源时都无法检查缓存源的状态是一个很大的问题,因为缓存数据可能已过时但用户在同一浏览器实例中发出后续请求之前不会知道它.

aps*_*ers 8

这里发生了两件事:

  1. Chrome的缓存过于激烈.

  2. ifModified=true也许不会那么做什么,你认为它.

Chrome应始终向服务器发送请求以验证缓存资源的有效性,但有时它似乎根本不会.这种行为常常使Web开发人员在开发期间迅速改变其资源受挫.

JavaScript只能304在发出请求的脚本显式设置缓存标头时观察响应.JavaScript无法利用浏览器已知的缓存日期信息; 任何缓存日期信息必须由脚本本身发现或选择(可能通过读取先前响应的最后修改的标题).除非JavaScript设置标头(或其他缓存标头),否则304将向浏览器报告的实际响应将作为200响应报告给JavaScript If-Modified-Since.

使用jQuery首次获取资源将永远不会返回304.这是因为jQuery不保存值与If-Modified-Since页面加载之间的标头一起使用.请参阅我的答案如何检查jQuery.ajax()请求标头状态是否为"304 Not Modified"?:

但是,jQuery不会在页面重新加载之间保留缓存信息(例如,在cookie中).因此,页面重新加载后第一次获取资源永远不会是304,因为jQuery没有要发送的缓存信息(即,我们重置回"第一次获取"情况).jQuery没有理由不能保留缓存信息,但目前它没有.

这样的原因是304请求总是空回来.假设您的代码在第一次以200返回时存储响应,但jQuery不希望强制要求您在页面重新加载时保存缓存结果.