jQuery-1.9.1源碼分析系列(十六)ajax——響應資料處理和api整理

來源:互聯網
上載者:User

標籤:

  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-Typewhile (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文檔中匹配選取器的部分內容來替換當前匹配元素的內容。如果該文檔沒有匹配選取器的內容,就使用Null 字元串("")來替換當前匹配元素的內容。

如果當前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請求。如果傳入的不是數組或"純粹的對象",則返回Null 字元串("");如果傳入的是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版本的源碼分析完畢。歡迎拍磚指正。

 

  如果覺得本文不錯,請點擊右下方【推薦】!

jQuery-1.9.1源碼分析系列(十六)ajax——響應資料處理和api整理

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.