Chrome: You will die!
IE9: Not today!
複製代碼
搭建公司官網的框架時採用了 vuejs, 使用 history router mode 來作 SEO 優化, 使用 fetch 作網絡請求, fetch 用 whatwg-fetch 作 polyfill. 根據百度瀏覽器市場份額統計, 2017年整年 IE9 的佔有率達到 9.50%, 而且 vue 框架也是兼容到 IE9, 因此要求項目兼容到 IE9.vue
可是 fetch polyfill 並不兼容 IE9, 這篇文章追溯問題緣由並提出解決方法.git
在 IE9 下打開頁面, 發現 fetch 請求報了Unhandled promise rejectionError: 拒絕訪問
:github
IE9 ajax
IE11 開 IE9 調試模式 shell
懷疑是 fetch 的兼容問題, 查看一下版本:npm
$npm list whatwg-fetch
project
└── whatwg-fetch@2.0.3
複製代碼
查看了一下whatwg-fetch 兼容性: 只支持到 IE10. 而後看到 whatwg-fetchv0.11 能夠兼容 IE9, 那就降級一下吧:json
$ npm uninstall whatwg-fetch
removed 1 package in 4.851s
$ npm install whatwg-fetch@0.11
+ whatwg-fetch@0.11.1
added 1 package in 5.96s
複製代碼
再試一下, 發現仍是同樣的問題.跨域
XMLHttpRequest
不支持 CORSfetch 的 polyfill 採用了 XMLHttpRequest 實現, 可是在 IE9 下面, XMLHttpRequest 是不支持跨域請求的. IE10 的 XMLHttpRequest
支持跨域, 而 IE8, IE9 須要使用 XDomainRequest 來實現跨域.promise
那就用 XDomainRequest
實現異步請求, 代碼:瀏覽器
function fetchIe9(url, options = {}) => {
if (window.XDomainRequest) {
// https://developer.mozilla.org/en-US/docs/Web/API/XDomainRequest
// only support GET and POST method
// request and response content type should be JSON
// without response status code
return new Promise((resolve, reject) => {
const method = options.method || 'GET';
const timeout = options.timeout || 30000;
let data = options.body || options.params || {};
if (data instanceof Object) {
data = JSON.stringify(data);
}
const XDR = new XDomainRequest();
XDR.open(method, url);
XDR.timeout = timeout;
XDR.onload = () => {
try {
const json = JSON.parse(XDR.responseText);
return resolve(json.data);
} catch (e) {
reject(e);
}
return reject({});
};
XDR.ontimeout = () => reject('XDomainRequest timeout');
XDR.onerror = () => reject('XDomainRequest error');
XDR.send(data);
});
} else {
// native fetch or polyfill fetch(XMLHttpRequest)
// fetch...
}
}
複製代碼
須要注意的是:
XDomainRequest
只支持 GET 和 POST mehtodXDomainRequest
不支持帶 cookieXDomainRequest
不能設置 responseType
, 通訊雙方須要約定數據格式XDomainRequest
的響應沒有 response status code題外話: whatwg-fetch
一直採用 XMLHttpRequest
來作 polyfill, whatwg-fetch1.0+
不支持 IE9, 並非由於沒有采用 XDomainRequest
, 而是由於 IE9 的狀態碼不符合 fetch 規範, 而 polyfill 的目標是 polyfill 規範, 而不是作兼容.
寫好了代碼, 在 IE9 中, 網絡請求很是詭異, 常常不行: 請求只持續了不到 1ms, 而且接收數據爲 0B, 沒有狀態碼; 可是在少數時候是能夠成功請求並獲取數據的.
IE9
IE11 開 E9 調試模式 此時 IE11 的 IE9 調試模式是能夠的, 看來模擬器仍是模擬不到位.
查了很久, 終於看到一篇文章: Internet Explorer Aborting AJAX Requests : FIXED
IE timing out the request even though data is being transmitted.
主要的緣由大概是 IE9 會將一個正在傳輸的請求 timeout 掉.
解決辦法是:
onprogress
事件回調, 告知 IE9 這個請求是活動中的, 不要 timeout 掉.function fetchIe9(url, options = {}) => {
if (window.XDomainRequest) {
// https://developer.mozilla.org/en-US/docs/Web/API/XDomainRequest
// only support GET and POST method
// request and response content type should be JSON
// without response status code
return new Promise((resolve, reject) => {
const method = options.method || 'GET';
const timeout = options.timeout || 30000;
let data = options.body || options.params || {};
if (data instanceof Object) {
data = JSON.stringify(data);
}
const XDR = new XDomainRequest();
XDR.open(method, url);
XDR.timeout = timeout;
XDR.onload = () => {
try {
const json = JSON.parse(XDR.responseText);
return resolve(json.data);
} catch (e) {
reject(e);
}
return reject({});
};
// fix random aborting: https://cypressnorth.com/programming/internet-explorer-aborting-ajax-requests-fixed/
XDR.onprogress = () => {};
XDR.ontimeout = () => reject('XDomainRequest timeout');
XDR.onerror = () => reject('XDomainRequest error');
setTimeout(() => {
XDR.send(data);
}, 0);
});
} else {
// native fetch or polyfill fetch(XMLHttpRequest)
// fetch...
}
}
複製代碼
XDomainRequest
, 由於 IE9 下的 XMLHttpRequest
不支持跨域調用.XDomainRequest
只支持 GET 和 POST method, 而且沒有 response status code, 能夠說是不完善的 HTTP 異步請求對象.whatwg-fetch1.0+
不支持 IE9, 是由於 IE9 的狀態碼不符合 fetch 規範, 而 polyfill 的目標是 polyfill 規範, 而不是作兼容.https://developer.mozilla.org/en-US/docs/Web/API/XDomainRequest
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
https://blogs.msdn.microsoft.com/ieinternals/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds/
https://cypressnorth.com/programming/internet-explorer-aborting-ajax-requests-fixed/