Firefox: Promise.then не называется асинхронно
Я прочитал спецификацию Promise/A + и в разделе 2.2.4:
onFulfilled или onRejected не должны вызываться, пока стек контекста выполнения не содержит только код платформы
Но в Firefox (я тестировал 38.2.1 ESR и 40.0.3) следующий script синхронно выполняет синхронный метод onFulfilled:
var p = Promise.resolve("Second");
p.then(alert);
alert("First");
(Кажется, он не запускается с помощью предупреждений, здесь также можно попробовать: http://jsbin.com/yovemaweye/1/edit?js,output)
Он работает так, как ожидалось, в других браузерах или при использовании ES6Promise- Polyfill.
Я что-то пропустил? Я всегда, хотя одна из точек тогда-метода заключается в обеспечении асинхронного выполнения.
Изменить:
Он работает при использовании console.log, см. ответ Benjamin Gruenbaum:
function output(sMessage) {
console.log(sMessage);
}
var p = Promise.resolve("Second");
p.then(output);
output("First");
Как он замечает в комментариях, это также происходит при использовании синхронных запросов, и именно поэтому это происходит в вашем тестовом сценарии.
Я создал минимальный пример того, что происходит в наших тестах:
function request(bAsync) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.addEventListener("readystatechange", function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
resolve(xhr.responseText);
}
});
xhr.open("GET", "https://sapui5.hana.ondemand.com/sdk/resources/sap-ui-core.js", !!bAsync);
xhr.send();
});
}
function output(sMessage, bError) {
var oMessage = document.createElement("div");
if (bError) {
oMessage.style.color = "red";
}
oMessage.appendChild(document.createTextNode(sMessage));
document.body.appendChild(oMessage);
}
var sSyncData = null;
var sAsyncData = null;
request(true).then(function(sData) {
sAsyncData = sData;
output("Async data received");
});
request(false).then(function(sData) {
sSyncData = sData;
output("Sync data received");
});
// Tests
if (sSyncData === null) {
output("Sync data as expected");
} else {
output("Unexpected sync data", true);
}
if (sAsyncData === null) {
output("Async data as expected");
} else {
output("Unexpected async data", true);
}
Ответы
Ответ 1
Это связано с тем, что вы используете alert
При использовании alert
здесь он блокирует и все ставки отключены - страница заблокирована, выполнение остановлено, и все находится на "уровне платформы".
Это может считаться ошибкой, и это, конечно, не то, что я ожидаю, но в основном это касается несовместимости между alert
и семантикой задачи/микрозадачи JavaScript.
Если вы измените это предупреждение на console.log
или добавив к document.innerHTML
, вы получите ожидаемый результат.
var alert = function(arg) { // no longer a magical and blocking operation
document.body.innerHTML += "<br/>" + arg;
}
// this code outputs "First, Second, Third" in all the browsers.
setTimeout(alert.bind(null, "Third"), 0);
var p = Promise.resolve("Second");
p.then(alert);
alert("First");