jQuery ajax 響應資料處理

來源:互聯網
上載者: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-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),所以他會預設dataType為html。你還可以在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 字元串("");如果傳入的是null、undefined等無法訪問屬性的值,則直接報錯。

所謂"純粹的對象",就是通過{}或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的Ajax時無響應資料的解決方案

$.ajax({

    type: "POST",

    url: "/MemberComment.aspx/GetOrderToBeCommentCount",

    success: function(result) {

    //ToDo:

})

使用時JS也沒有報錯。這個是我最鬱悶的事了。不知道哪錯。。



從c#代碼到瀏覽器一個個排查問題發現都OK。

最後問題的原因是改為如下就OK,少了2個屬性:


$.ajax({

    type: "POST",

    contentType: "application/json",

    url: "/MemberComment.aspx/GetOrderToBeCommentCount",

    data:"{a:'a'}",

    success: function(result) {

    //ToDo:

    }
})

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.