I think what happens:
- JavaScript has an event queue.
- IE handles timeouts and queues two events.
- The first timeout event is processed, and clearTimeout is called for B. However, the event for B is already queued, so it still fires.
- the second timeout event is processed, and clearTimeout is called for A.
I suspect that in IE the event is queued and calling clearTimeout does not remove the event from the event queue.
It is also possible that there is simply a fake way in which IE pushes simultaneous timeouts into the queue ... The root cause can be diagnosed using two different timeouts, using 100% of the processor cycles for x time, and also by queues / (maybe it can insert events into the queue using window.postMessage () and catch them using window.onMessage ()).
I modified your existing code to better show the problem. It queues log items, rather than doing them immediately, because calling display () can cause layout or rendering, which can easily introduce other funky clutter.
Edit: you can test this using http://jsbin.com/ucukez/2 - if the browser has an error, then you get "A timeout fired" and msgstr "in standby mode".
Edit: this was fixed in IE9 - I could not reproduce in 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>
source share