zoukankan      html  css  js  c++  java
  • jQuery-1.9.1源码分析系列(十六)ajax——响应数据处理和api整理

      ajax在得到请求响应后主要会做两个处理:获取响应数据和使用类型转化器转化数据

    a.获取响应数据


      获取响应数据是调用ajaxHandleResponses函数来处理。

      ajaxHandleResponses的功能有:

      - 为jqXHR设置所有responseXXX字段(值便是响应数据)

      - 找到正确的dataType (在content-type和预期的dataType两者中的一个)

      - 返回正确的响应数据

      我们看一个响应数据的格式:

      responses = {
        text: "{"code":500,"data":null,"message":"all exist","sessionId":"wsdfhl333sdfs"}"
      }

      设置responseXXX只有两种responseXML和responseText

        //填写responseXXX(responseXML/responseText)字段,
        for ( type in responseFields ) {
            if ( type in responses ) {
                jqXHR[ responseFields[type] ] = responses[ type ];
            }
        }

      找到正确的dataType。这是一个逐一探测的过程

        // 除去自动添加的dataType类型,同时在此过程中获得Content-Type类型
        while( dataTypes[ 0 ] === "*" ) {
            dataTypes.shift();
            if ( ct === undefined ) {
                ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
            }
        }
    
        //检查我们是否正在处理一个已知的content-type
        if ( ct ) {
            for ( type in contents ) {
                if ( contents[ type ] && contents[ type ].test( ct ) ) {
                    dataTypes.unshift( type );
                    break;
                }
            }
        }
    
        //检查看看我们是否有预期的数据类型的响应
        if ( dataTypes[ 0 ] in responses ) {
            finalDataType = dataTypes[ 0 ];
        } else {
            //尝试可转换的数据类型
            for ( type in responses ) {
                if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
                    finalDataType = type;
                    break;
                }
                if ( !firstDataType ) {
                    firstDataType = type;
                }
            }
            // Or just use first one
            finalDataType = finalDataType || firstDataType;
        }

      返回正确的响应数据

        // 如果我们找到一个dataType
        // 把dataType到dataTypes中去,如果需要的话
        // 返回相应的响应数据
        if ( finalDataType ) {
            if ( finalDataType !== dataTypes[ 0 ] ) {
                dataTypes.unshift( finalDataType );
            }
         return responses[ finalDataType ];
      }
    }

    b.类型转化器


      ajax有四种转换器

    converters: {
               // 任意内容转换为字符串
               // window.String 将会在min文件中被压缩为 a.String
               "* text": window.String,
     
               // 文本转换为HTML(true表示不需要转换,直接返回)
               "text html": true,
     
               // 文本转换为JSON对象
               "text json": jQuery.parseJSON,
     
               // 文本转换为XML
               "text xml": jQuery.parseXML
           }

      其中jQuery.parseJSON/jQuery.parseXML点击看详情

      除此之外还有为script专门拓展的

    // Ajax请求设置默认的值
    jQuery.ajaxSetup({
        /**
         * 内容类型发送请求头(Content-Type),用于通知服务器该请求需要接收何种类型的返回结果。
         * 如果accepts设置需要修改,推荐在$.ajaxSetup() 方法中设置一次。
         * @type {Object}
         */
        accepts: {
            script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
        },
        contents: {
            script: /(?:java|ecma)script/
        },
        converters: {
            "text script": function(text) {
                jQuery.globalEval(text);
                return text;
            }
    }

      还有一个在jsonp预处理的时候添加的

                s.converters["script json"] = function() {
                    if ( !responseContainer ) {
                        jQuery.error( callbackName + " was not called" );
                    }
                    return responseContainer[ 0 ];
                };

      dataType无非就那么几种情况

      1:dataType为空,自动转化

      此时jQuery只能根据报文头信息是猜测当前需要处理的类型(ajaxHandleResponses中)

    // 删除掉通配dataType,得到返回的Content-Type
    while (dataTypes[0] === "*") {
        dataTypes.shift();
        if (ct === undefined) {
            ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
        }
    }

      通过xhr.getAllResponseHeaders()得到报文头信息,然后去匹配Content-Type所有对象的值即可

      当然找到这个Content-Type = “html”,我们还得看看有没有对应处理的方法,如果有就需要替换这个dataTypes(ajaxHandleResponses中)

    // 看看是不是我们能处理的Content-Type,比如图片这类二进制类型就不好处理了
    if (ct) {
        // 实际上能处理的就是text、xml和json
        for (type in contents) {
            if (contents[type] && contents[type].test(ct)) {
                dataTypes.unshift(type);
                break;
            }
        }
    }

      经过这个流程后,dataTypes 本来是* 就变成了对应的html了,这是jquery内部的自动转化过程。

      2:dataType开发者指定 

      xml, json, script, html, jsop

      

      最终ajax成功以后统一调用ajaxConvert函数处理。所以转换器总结起来就一句话:类型转换器将服务端响应的responseText或responseXML,转换为请求时指定的数据类型dataType,如果没有指定类型就依据响应头Content-Type自动处理。根据目标类型选择响应的转换器转换成目标数据。

      

    c. jQuery. ajaxSetup ( target[, settings] )


      函数如果用于外部使用没有settings这个参数:用于设置AJAX的全局默认设置。

      这个函数有两个用法

      1.当target、settings两个参数传递的时候,创建一个完整成熟的设置对象(包含ajaxSettings和传递的settings)写入到target中。最终jQuery.ajaxSettings这个全局变量没有改变。这个用法主要是jQuery内部使用,外部使用没有意义。

      2.当settings不存在的时候(即只有一个参数),则将target写入jQuery.ajaxSettings。这个用法在外部使用较多。主要是设置AJAX的全局默认设置。

      查看源码

    //创建一个完整成熟的设置对象(包含ajaxSettings和传递的settings)写入到target中。
    //如果settings省略,则将target写入ajaxSettings.
    ajaxSetup: function( target, settings ) {
        return settings ?
            ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
            ajaxExtend( jQuery.ajaxSettings, target );
    }

      使用到ajaxExtend函数,通过jQuery.ajaxSettings.flatOptions指定那些选项不做深度拓展(深度拷贝替换),其他的都做深度拓展。默认的不做深度拓展的选项只有两个jQuery.ajaxSettings.flatOptions: {url: true,context: true}。外部可以直接将不做深度拓展的选项添加到jQuery.ajaxSettings.flatOptions上

    //为ajax选项专门做拓展的函数
    //对flatOptions里面的选项(不需要深度拓展(深度拷贝替换))
    function ajaxExtend( target, src ) {
        var deep, key,
            flatOptions = jQuery.ajaxSettings.flatOptions || {};
    
        //针对不需要深度拓展的选项保存在target[key]中,需要深度拓展的选项保存在deep[key]中。
        for ( key in src ) {
            if ( src[ key ] !== undefined ) {
                ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
            }
        }
        //将deep中的内容深度拓展(深度拷贝替换)到target中
        if ( deep ) {
            jQuery.extend( true, target, deep );
        }
        return target;
    }

    d. ajax相关api


    jQuery.get(url [, data ] [, success ] [, type ])函数用于通过HTTP GET形式的AJAX请求获取远程数据。

    jQuery.get()函数用于实现简单的GET形式的AJAX请求,它在底层是使用jQuery.ajax()来实现的,只是省略了大多数不常用的参数设置,并仅限于HTTP GET方式。请注意,该函数是通过异步方式加载数据的。这里介绍的jQuery.get()是一个全局方法(无需创建jQuery对象即可调用,你可以理解为静态函数)。jQuery中还有一个同名的实例方法get(),用于获取当前jQuery对象中匹配的指定索引的DOM元素。)

    jQuery.post(url [, data ] [, success ] [, type ])函数用于通过HTTP POST形式的AJAX请求获取远程数据

    jQuery.post()函数用于实现简单的POST形式的Ajax请求,它在底层是使用jQuery.ajax()来实现的,只是省略了大多数不常用的参数设置,并仅限于HTTP POST方式。请注意,该函数是通过异步方式加载数据的)

    jQuery.getJSON(url [, data ] [, success ])函数用于通过HTTP GET形式的AJAX请求获取远程JSON编码的数据。JSON是一种数据格式,JS原生支持JSON格式,通过jQuery.getJSON()从服务器获得的JSON数据,jQuery会先尝试将其转为对应的JS对象。如果请求的URL中包括"callback=?"等类似的部分,jQuery会自动将其视作JSONP,并执行对应的回调函数来获取JSON数据。

    重要注意:服务器返回的JSON数据必须符合严格的JSON语法,例如:所有属性名称必须加双引号,所有字符串值也必须加双引号(而不是单引号)。请注意,该函数是通过异步方式加载数据的。)

    jQuery.getScript(url [, success ])函数用于通过HTTP GET形式的加载JavaScript文件并运行它。该函数用于动态加载JS文件,并在全局作用域下执行文件中的JS代码。该函数可以加载跨域的JS文件。请注意,该函数是通过异步方式加载数据的)

    jQuery.fn.load(url [, data ] [, complete ])函数用于从服务器加载数据,并使用返回的html内容替换当前匹配元素的内容。load()函数默认使用GET方式,如果提供了对象形式的数据,则自动转为POST方式。load()函数只会替换每个匹配元素的内部内容(innerHTML),所以他会默认dataTypehtml。你还可以在URL字符串后面追加指定的选择器(与URL之间用空格隔开),以便于只使用加载的html文档中匹配选择器的部分内容来替换当前匹配元素的内容。如果该文档没有匹配选择器的内容,就使用空字符串("")来替换当前匹配元素的内容。

    如果当前jQuery对象没有匹配任何元素,则不会执行远程加载请求。

    这里介绍的load()是一个Ajax请求函数,jQuery中还有一个同名的事件函数load(),用于在文档加载完成时执行指定的函数。该函数属于jQuery对象(实例)。该函数在底层是基于函数jQuery.ajax()实现的)

    jQuery.ajaxPrefilter([ dataType ,] handler)函数用于指定预先处理Ajax参数选项的回调函数。在所有参数选项被jQuery.ajax()函数处理之前,你可以使用该函数设置的回调函数来预先更改任何参数选项。

      你还可以指定数据类型(dataType),从而只预先处理指定数据类型的参数选项。该函数可以调用多次,以便于为不同数据类型的AJAX请求指定不同的回调函数

      dataType(可选/String类型)

      一个或多个用空格隔开的数据类型所组成的字符串。如果未指定该参数,则表示所有数据类型。可用的数据类型为"xml"、 "html"、 "text"、 "json"、 "jsonp"、 "script"。该字符串为它们之间的任意组合(多种类型用空格隔开),例如:"xml"、 "text html"、 "script json jsonp"。

      handler (Function类型)

      用于预处理参数选项的回调函数。它有以下3个参数:

      options:(Object对象)当前AJAX请求的所有参数选项。

      originalOptions:(Object对象)传递给$.ajax()方法的未经修改的参数选项。

      jqXHR:当前请求的jqXHR对象(经过jQuery封装的XMLHttpRequest对象)。

    jQuery.ajaxSetup(settingsObj) (函数用于设置AJAX的全局默认设置。该函数用于更改jQuery中AJAX请求的默认设置选项。之后执行的所有AJAX请求,如果对应的选项参数没有设置,将使用更改后的默认设置。)

    jQuery.fn.serialize()(函数用于序列化一组表单元素,将表单内容编码为用于提交的字符串。serialize()函数常用于将表单内容序列化,以便用于AJAX提交。

      该函数主要根据用于提交有效表单控件的name和value,将它们拼接为一个可直接用于表单提交的文本字符串,该字符串已经过标准的URL编码处理(字符集编码为UTF-8)。

      该函数不会序列化不需要提交的表单控件,这和常规的表单提交行为是一致的。例如:不在<form>标签内的表单控件不会被提交、没有name属性的表单控件不会被提交、带有disabled属性的表单控件不会被提交、没有被选中的表单控件不会被提交。

      与常规表单提交不一样的是:常规表单一般会提交带有name的按钮控件,而serialize()函数不会序列化带有name的按钮控件。)

    jQuery.fn.serializeArray()(函数用于序列化一组表单元素,将表单内容编码为一个JavaScript数组。常用于将表单内容序列化为JSON对象,以便于被编码为JSON格式的字符串。

      该函数会将可用于提交的每个表单控件封装成一个Object对象,该对象有name和value属性,对应该表单控件的name和value属性。然后将这些Object对象封装为一个数组并返回。

      该函数不会序列化不需要提交的表单控件,这和常规的表单提交行为是一致的。例如:不在<form>标签内的表单控件不会被提交、没有name属性的表单控件不会被提交、带有disabled属性的表单控件不会被提交、没有被选中的表单控件不会被提交。

      与常规表单提交不一样的是:常规表单一般会提交带有name的按钮控件,而serializeArray()函数不会序列化带有name的按钮控件。)

    jQuery.param(obj [, traditional ])将一个JS数组或纯粹的对象序列化为字符串值,以便用于URL查询字符串或AJAX请求。如果传入的不是数组或"纯粹的对象",则返回空字符串("");如果传入的是nullundefined等无法访问属性的值,则直接报错。

      所谓"纯粹的对象",就是通过{}new Object()自行创建的对象。JS内置的Boolean、Number、String、Date、RegExp、Function、Window等类型的对象都不算是"纯粹的对象"。

      返回的字符串已经过URL编码处理(采用的字符集为UTF-8))

    jQuery.fn.ajaxStart(handlerFn)(为AJAX请求的ajaxStart事件绑定处理函数)

    jQuery.fn.ajaxSend(handlerFn)(设置当AJAX请求即将被发送时执行的回调函数。)

    jQuery.fn.ajaxComplete(handlerFn)(设置当AJAX请求完成(无论成功或失败)时执行的回调函数。)

    jQuery.fn.ajaxSuccess(handlerFn)(设置当AJAX请求成功完成时执行的回调函数。)

    jQuery.fn.ajaxError(handlerFn)(设置当AJAX请求失败时执行的回调函数。)

    jQuery.fn.ajaxStop(handlerFn)(为AJAX请求的ajaxStop事件绑定处理函数。)

      

      到此为止,jQuery 1.9.1版本的源码分析完毕。欢迎拍砖指正。

  • 相关阅读:
    CSS3 target伪类简介
    不用position,让div垂直居中
    css3 在线编辑工具 连兼容都写好了
    a标签伪类的顺序
    oncopy和onpaste
    【leetcode】1523. Count Odd Numbers in an Interval Range
    【leetcode】1518. Water Bottles
    【leetcode】1514. Path with Maximum Probability
    【leetcode】1513. Number of Substrings With Only 1s
    【leetcode】1512. Number of Good Pairs
  • 原文地址:https://www.cnblogs.com/chuaWeb/p/jQuery-1-9-1-ajax-3.html
Copyright © 2011-2022 走看看