當我們的 SAP UI5 應用裡使用了 OData 模型從遠端伺服器讀取資料,具體實現細節可以參考我這篇文章:SAP UI5 初學者教程之二十四 - 如何使用 OData 資料模型,可以在 Chrome 開發者工具裡,觀察到一個由 SAP UI5 框架自動發出的後設資料請求。
請求的 url :
https://services.odata.org/V2...$metadata?sap-language=EN
該請求沒有 content-type 欄位,只有一個 accept 欄位,值為:application/xml
還有一個 MaxDataServiceVersion,值為 3.0
響應的頭部欄位裡,沒有 Accept 欄位,只有 Content-Type 欄位,注意大小寫:
具體發起該 HTTP 請求的程式碼位置:ODataMetadata 的 _loadMetadata 方法:
在建構函式里觸發 _loadMetadata:
基於 url 建立 request 物件:
根據如下的 API 獲得 HTTP 請求支援的語言:Accept-Language
sap.ui.getCore().getConfiguration().getLanguageTag()
計算出來是:en-US
bAsync 標誌位為 true,代表這是個非同步請求:
withCredentials 標誌位為 false:
然後使用傳統的 promise API 發起請求:
如果 metadata 載入成功,就在其回撥裡執行初始化邏輯:
if (!this.oMetadata.isLoaded()) {
this.oMetadata.attachFailed(this.onMetadataFailed);
}
下面呼叫 OData API,傳入剛才構造好的請求物件,進行請求傳送:
進入 datajs.js, 首先 prepareRequest:
normalizeHeaders:對頭部欄位進行規範化處理,其實就是將頭部欄位轉換成小寫:
然後呼叫 invokeRequest 進行傳送:
移交給 httpClient:
datajs.js 的底層還是基於 XHR 即 XmlHttpRequest:
直接使用瀏覽器原生的 XMLHttpRequest:
這裡的 fallback 機制用的是已經很古老的 ActiveXObject 了,現代瀏覽器都不會執行到:
var createXmlHttpRequest = function () {
/// <summary>Creates a XmlHttpRequest object.</summary>
/// <returns type="XmlHttpRequest">XmlHttpRequest object.</returns>
if (window.XMLHttpRequest) {
return new window.XMLHttpRequest();
}
var exception;
if (window.ActiveXObject) {
try {
return new window.ActiveXObject("Msxml2.XMLHTTP.6.0");
} catch (_) {
try {
return new window.ActiveXObject("Msxml2.XMLHTTP.3.0");
} catch (e) {
exception = e;
}
}
} else {
exception = { message: "XMLHttpRequest not supported" };
}
throw exception;
};
最後呼叫 xhr.open:
使用 send api 進行請求傳送。
更多Jerry的原創文章,盡在:"汪子熙":