zoukankan      html  css  js  c++  java
  • jquery.ajax中的ifModified参数的误解

    原来以为ifModified是为了在AJAX请求是发送 If-Modified-Since头,让服务端返回304。

    测试代码如下:

     

    $(function () {
        test();
        window.setTimeout(test, 5000);
    });
    
    function test() {
        $.ajax({
            type: "GET",
            url: url,
            ifModified: true,
            success: function (d, textStatus, xhr) {
               console.log(xhr.status);
    	    console.log(d == undefined);
            }
        });
    }

    chrome:

    network 为 304,304

    console为  200 false, 304 true

    ie10

    network为 304, 304

    console为 200 false, 304 true

    firefox:

    network为 304, 200(from cache)

    console为 200 false, 200 false

    上述测试是建立在已经访问过的基础上进行的,因此第一个请求都为304。

    测试结果有几个疑问

    1、为什么network监控的响应码与jqXHR.status有不一致的情况

    2、chrome与ie10为什么第一次请求可以获取到内容,但同样的304返回,第二次却内容为undefined

    3、firefox的第二次请求为什么直接从cache取数据

    据文档 XHR API

    For 304 Not Modified responses that are a result of a user agent generated conditional request the user agent must act as if the server gave a 200 OK response with the appropriate content. The user agent must allow setRequestHeader() to override automatic cache validation by setting request headers (e.g., If-None-Match, If-Modified-Since), in which case 304 Not Modified responses must be passed through.

    就是说一般情况下,如果服务器返回304后,浏览器会进行转换。此时jqXHR.status应该是200,并且浏览器会自动将缓存的内容发送给jqXHR(304,服务器是不会发送内容信息的);

    但可以通过jqXHR.setRequestHeader(If-Modified-Since)来重载该行为,如果服务端会返回304,则把该结果直接传递给 jqXHR。

    据此我们回答了第一个疑问。

    那么第二个问题是怎么回事?

    查看了network中的请求,二次请求都有带 If-Modified-Since 的头,没什么发现

    在jq的源码发现了以下代码

    // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
    if ( s.ifModified ) {
    
    	if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
    		jQuery.lastModified[ ifModifiedKey ] = lastModified;
    	}
    	if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
    		jQuery.etag[ ifModifiedKey ] = etag;
    	}
    }

    这是从响应获取Last-Modified头的过程

    // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
    if ( s.ifModified ) {
    	ifModifiedKey = ifModifiedKey || s.url;
    	if ( jQuery.lastModified[ ifModifiedKey ] ) {
    		jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
    	}
    	if ( jQuery.etag[ ifModifiedKey ] ) {
    		jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
    	}
    }

    这是设置If-Modified-Since头的过程

    回到主题 ifModified 参数,文档如下

    Allow the request to be successful only if the response has changed since the last request. This is done by checking the Last-Modified header. Default value is false, ignoring the header. In jQuery 1.4 this technique also checks the 'etag' specified by the server to catch unmodified data.

    文档说得不是很清楚,看代码的实现。

    jq根据jQuery.lastModified字典中是否包含数据来决定是否设置If-Modified-Since。那第一次请求jQuery.lastModified是没有数据的(JS是无法获取浏览器缓存的信息),因此第一次请求jqXHR是没有设置If-Modified-Since,那也就解释了第一次请求jqXHR.status为200。因为有了第一次请求,jq获取获取到第一次请求响应中的Last-ModifiedjQuery.lastModified有了数据,第二次请求jqXHR是会加上If-Modified-Since头的,因此jqXHR.status收到了浏览器直接传递过来的请求响应及内容。

    搞定了第二个疑问。

    第三个问题看了一些文档还没有明确的结论,估计是firefox在xhr在处理cache上有些不同,服务器响应头有包含

    Cache-Control:public, max-age=18000

    总结下:

    jquery ifModified参数主要是为了在通过JS检测资源是否发生变化(304),并且在页面的第一个AJAX请求jqXHR.status永远不会返回304。

    参考文档

    1、http://www.w3.org/TR/2009/WD-XMLHttpRequest-20091119/

    2、http://stackoverflow.com/questions/5173656/how-to-check-if-jquery-ajax-request-header-status-is-304-not-modified

    3、https://bugzilla.mozilla.org/show_bug.cgi?id=428916

  • 相关阅读:
    MyBatis通过JDBC生成的执行语句问题
    request.getParameter()、request.getInputStream()和request.getReader()
    Spring 实现数据库读写分离
    图片分布式存储
    切换城市的功能实现
    一直在前进的路上
    test blog
    SSIS 系列
    微信摇一摇优惠券
    扫描二维码实现一键登录
  • 原文地址:https://www.cnblogs.com/vime/p/3210414.html
Copyright © 2011-2022 走看看