Я думаю, что происходит так:
- У JavaScript есть очередь событий.
- IE обрабатывает тайм-ауты и ставит в очередь два события.
- Первое событие тайм-аута обрабатывается, и clearTimeout вызывается для B. Однако событие для B уже поставлено в очередь, поэтому оно все равно запускается.
- обрабатывается второе событие тайм-аута, и вызывается clearTimeout для A.
Я подозреваю, что в IE событие ставится в очередь, и вызов clearTimeout не удаляет событие из очереди событий.
Также возможно, что в том, как IE выдвигает одновременные тайм-ауты в очередь, есть просто причудливость ... Диагностика основной причины может быть достигнута с помощью двух разных тайм-аутов, с использованием 100% циклов обработки ЦП на время x и с помощью очереди / создание временных интервалов в других событиях (возможно, можно добавить события в очередь с помощью window.postMessage () и перехватить их с помощью window.onMessage ()).
Я изменил ваш существующий код, чтобы лучше продемонстрировать проблему. Он ставит в очередь элементы журнала, а не делает их немедленно, потому что вызов метода display () может вызвать разметку или рендеринг, что может легко привести к другим бесполезным помехам.
Редактировать: Вы можете проверить это, используя http://jsbin.com/ucukez/2 - если в браузере возникла ошибка, вы получите "в течение тайм-аута" и"в тайм-ауте B".
Редактировать: это было исправлено в IE9 - я не мог воспроизвести в IE9 / IE10 / IE11.
HTML-код:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>setTimeout queued test</title>
<script>
function display(txt) {
document.getElementById('logger').innerHTML += txt + '<br>';
}
var log = {
items: [],
push: function(text) {
this.items.push(text);
},
display: function() {
var items = this.items;
this.items = [];
for (var i = 0; i < items.length; i++) {
display(items[i]);
}
}
};
function startTest() {
var ms = 10;
display("startTest()");
log.push('before A setTimeout');
var a = setTimeout(function(){
log.push('in A timeout fired');
display("A fired!");
log.push('in A clear timer B');
clearTimeout(b);
log.push('in A cleared timer B');
}, ms);
log.push('after A setTimeout');
log.push('before B setTimeout');
var b = setTimeout(function(){
log.push('in B timeout fired');
display("B fired!");
log.push('in B clear timer A');
clearTimeout(a);
log.push('in B cleared timer A');
}, ms);
log.push('after B setTimeout');
setTimeout(function(){
display("");
display("Displaying logged items:");
log.display();
},1000);
}
</script>
</head>
<body onload="startTest()">
<div id="logger"></div>
</body>
</html>