Chrome: You will die!
IE9: Not today!
задний план
При построении каркаса официального сайта компании используется vuejs, для SEO-оптимизации используется режим маршрутизатора истории, для сетевых запросов используется fetch, а для fetch используется полифилл с whatwg-fetch.Статистика доли рынка браузера Baidu, доля IE9 за весь 2017 год достигла9.50%, а платформа vue также совместима с IE9, поэтому проект должен быть совместим с IE9.
Но полифил выборки не совместим с IE9, в этой статье прослеживается причина проблемы и предлагается решение.
Проблема: доступ запрещен
Откройте страницу в IE9 и обнаружите, что сообщается о запросе на выборку.Unhandled promise rejectionError: 拒绝访问
:
-
IE9
-
IE11 открывает режим отладки IE9
Подозревают проблему совместимости с fetch, проверьте версию:
$npm list whatwg-fetch
project
└── whatwg-fetch@2.0.3
Проверьте этосовместимость с whatwg-fetch: поддерживает только до IE10. Затем см.whatwg-fetchv0.11 совместим с IE9, затем понизить:
$ 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
Попробуйте снова,Нашел такую же проблему.
Причина проблемы: IE9XMLHttpRequest
КОРС не поддерживается
Полифил выборки реализован с использованием XMLHttpRequest, но в IE9 XMLHttpRequest не поддерживает междоменные запросы.XMLHttpRequest
Поддержка междоменных доменов и IE8, IE9 необходимо использоватьXDomainRequestдля достижения междоменного.
затем используйте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. -
XDomainRequest
Не поддерживает куки -
XDomainRequest
не может быть установленresponseType
, обе стороны должны согласовать формат данных -
XDomainRequest
Ответ не имеет кода статуса ответа
Не по теме:whatwg-fetch
всегда используетсяXMLHttpRequest
сделать полифилл,whatwg-fetch1.0+
IE9 не поддерживается не потому, что он не принятXDomainRequest
, но потому чтоКод состояния IE9 не соответствует спецификации выборки, а такжеЦель полифилла — полифиллировать спецификацию, а не обеспечивать совместимость..
Проблема: запрос прерван и зависает
После написания кода, в IE9 сетевой запрос очень странный и часто дает сбой:Запрос длился менее 1 мс, а полученные данные — 0B, без кода состояния.; Но в редких случаях может успешно запрашивать и получать данные.
-
IE9
-
IE11 открывает режим отладки E9 На данный момент режим отладки IE9 IE11 в порядке, похоже, что эмулятор все еще не на месте.
После долгих поисков наконец нашел статью:Internet Explorer Aborting AJAX Requests : FIXED
IE timing out the request even though data is being transmitted.
Основная причина, вероятно, в том, что IE9 истечет время ожидания передаваемого запроса.
Решение:
- Добавить к
onprogress
Обратный вызов события, сообщает IE9, что этот запрос активен, не истечет время ожидания. - Отключите отправку запроса от основного потока, чтобы убедиться, что 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({});
};
// 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...
}
}
В заключение
- IE9 инициирует междоменный запрос на использование
XDomainRequest
, потому что в IE9XMLHttpRequest
Междоменные вызовы не поддерживаются. -
XDomainRequest
Поддерживаются только методы GET и POST, и нет кода статуса ответа, который можно назватьНесовершенный объект асинхронного запроса HTTP. - XDomainRequest не поддерживает указаниеresponseTypeРекомендовать использование запроса и возвращать соглашение о формате данных в виде JSON.
-
whatwg-fetch1.0+
IE9 не поддерживается, потому чтоКод состояния IE9 не соответствует спецификации выборки, а такжеЦель полифилла — полифиллировать спецификацию, а не обеспечивать совместимость..
References
- XDomainRequest
https://developer.mozilla.org/en-US/docs/Web/API/XDomainRequest
- XMLHttpRequest
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest
- XDomainRequest — ограничения, ограничения и обходные пути
https://blogs.msdn.microsoft.com/ieinternals/2010/05/13/xdomainrequest-restrictions-limitations-and-workarounds/
- Internet Explorer Aborting AJAX Requests : FIXED
https://cypressnorth.com/programming/internet-explorer-aborting-ajax-requests-fixed/