同事報案,某網頁使用jQuery.ajax()發出四個OData查詢,在Chrome執行正常,在IE時兩個AJAX呼叫正常,有兩個查不到資料。使用F12觀察,發現有問題的AJAX呼叫URL參數包含中文但未使用encodeURIComponent()編碼,Chrome正確地自動做了轉換,IE也自動做了轉換,但轉換結果出現亂碼。
URL未用encodeURIComponent()編碼要承擔敗戰責任無庸置疑,但jQuery.ajax()在不同瀏覽器結果不同這點挺有趣,值得調查,弄了精簡範例驗證這點:
<!DOCTYPEhtml>
<html>
<head>
<metacharset="utf-8"/>
</head>
<body>
<scriptsrc="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.12.4.js">
</script>
<script>
var url = "/_api/Query('執行緒')/items?$filter=Category eq '黑暗'";
$.get(url);
</script>
</body>
</html>
如圖所示,Chrome自動將URL中文部分成功轉成UTF8編碼:
而IE也做了轉換,但轉出亂碼:
換了jQuery 2.2.4甚至3.0.0,測試結果都相同。追入jQuery原始碼,jQuery.ajax()未對URL加工,交給瀏覽器內建XMLHttpRequest物件全權處理,換言之,是IE跟Chrome的XMLHttpRequest行為差異所致。
改寫程式碼如下,直接使用XMLHttpRequest,結果與jQuery.get()完全相同,證實全案的關鍵在於IE與Chrome XHR元件之URL轉換行為不同。
<!DOCTYPEhtml>
<html>
<head>
<metacharset="utf-8"/>
</head>
<body>
<scriptsrc="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.12.4.js">
</script>
<script>
var url = "/_api/Query('執行緒')/items?$filter=Category eq '黑暗'";
var oReq = new XMLHttpRequest();
oReq.open("get", url, true);
oReq.send();
</script>
</body>
</html>
結論,URL有中文或特殊字元請自行encodeURIComponent(),不要依賴瀏覽器自動轉換,以免因XHR處理邏輯不同產生非預期結果。