dataType 類型的轉(zhuǎn)化
dataType 類型的參數(shù),可以是 xml, json, script, or html 或者干脆為空,那么 jQuery 就需要一個方法去判斷當前是屬于什么數(shù)據(jù)處理,就此引入了 ajaxConvert 處理響應(yīng)轉(zhuǎn)化器,解析出正確的 dataType 類。
response = ajaxConvert(s, response, jqXHR, isSuccess);
分析下 dataType 無法就那么幾種情況
1. dataType 為空,自動轉(zhuǎn)化
此時 jQuery 只能根據(jù)頭部信息來猜測當前需要處理的類型,刪除掉通配 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”,我們還得看看有沒有對應(yīng)處理的方法,如果有就需要替換這個 dataTypes。
看看是不是我們能處理的 Content-Type,比如圖片這類二進制類型就不好處理了。
if (ct) { // 實際上能處理的就是text、xml和json for (type in contents) { if (contents[type] && contents[type].test(ct)) { dataTypes.unshift(type); break; } } }
經(jīng)過這個流程后,dataTypes 本來是 * 就變成了對應(yīng)的 html了,這是 jquery 內(nèi)部的自動轉(zhuǎn)化過。
2. dataType開發(fā)者指定
xml, json, script, html, jsop類型轉(zhuǎn)換器將服務(wù)端響應(yīng)的 responseText 或 responseXML,轉(zhuǎn)換為請求時指定的數(shù)據(jù)類型 dataType,如果沒有指定類型就依據(jù)響應(yīng)頭 Content-Type 自動處理。
類型轉(zhuǎn)換器的執(zhí)行過程
response = ajaxConvert(s, response, jqXHR, isSuccess);
流程
1.遍歷dataTypes中對應(yīng)的處理規(guī)則【"script","json"】 2.制作jqXHR對象的返回數(shù)據(jù)接口 json: "responseJSON" text: "responseText" xml: "responseXML" 如:jqXHR.responseText: "{"a":1,"b":2,"c":3,"d":4,"e":5}" 3.生成轉(zhuǎn)化器對應(yīng)的匹配規(guī)則,尋找合適的處理器 4.返回處理后的數(shù)據(jù)response
分析一下特殊的 jsonp 的轉(zhuǎn)化流程,先看看轉(zhuǎn)化對應(yīng)的處理器。
jsonp
converters["script json"] = function() { if (!responseContainer) { jQuery.error(callbackName + " was not called"); } return responseContainer[0]; };
jsonp 的轉(zhuǎn)化器只是很簡單的從 responseContainer 取出了對應(yīng)的值,所以 responseContainer 肯定在轉(zhuǎn)化之后就應(yīng)該把數(shù)據(jù)給轉(zhuǎn)化成數(shù)組對象了,當然做源碼分析需要一點自己猜想能力,比如 responseContainer 這個數(shù)組對象如何而來?
那么我們知道 jsonp 的處理的原理,還是通過加載 script,然后服務(wù)器返回一個回調(diào)函數(shù),responseContainer 數(shù)據(jù)就是回調(diào)函數(shù)的實參,所以需要滿足 responseContainer 的處理,必須要先滿足腳本先加載,所以我們要去分發(fā)器中找對應(yīng)的加載代碼,首先responseContainer 是內(nèi)部變量,只有一個來源處,在預(yù)處理的時候增加一個全局的臨時函數(shù),然后代碼肯定是執(zhí)行了這個函數(shù)才能把 arguments 參數(shù)賦給 responseContainer。
overwritten = window[callbackName]; window[callbackName] = function() { responseContainer = arguments; }; //callbcakName是內(nèi)部創(chuàng)建的一個尼瑪函數(shù)名 jQuery203029543792246840894_1403062512436 = function() { responseContainer = arguments; };
我們發(fā)送請求:
http://192.168.1.114/yii/demos/test.php?backfunc=jQuery203029543792246840894_1403062512436&action=aaron&_=1403062601515
服務(wù)器那邊就回調(diào)后,執(zhí)行了 jQuery203029543792246840894_1403062512436(responseContainer ) 所以全局的 callbackName 函數(shù)需要在分發(fā)器中腳本加載后才能執(zhí)行,從而才能截取到服務(wù)器返回的數(shù)據(jù)。
請驗證,完成請求
由于請求次數(shù)過多,請先驗證,完成再次請求
打開微信掃碼自動綁定
綁定后可得到
使用 Ctrl+D 可將課程添加到書簽
舉報