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/