澄清IE中的clearTimeout行为 [英] Clarifying clearTimeout behavior in IE

查看:95
本文介绍了澄清IE中的clearTimeout行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title></title>
    </head>
<body>
<div id="logger"></div>
<script>

function log(txt) {
    document.getElementById('logger').innerHTML += txt + '<br>';
}

var int = 10;
var a= setTimeout(function(){
    a = null;
    log("A fired!");
    clearTimeout(b);
    b = null;
}, int);

var b = setTimeout(function(){
    b = null;
    log("B fired!");
    clearTimeout(a);
    a = null;
}, int);


</script>

</body>
</html>

两个超时回调都应该阻止另一个超时回调。在Opera,FF和Chrome中只有第一个(打印A fired)被执行。但是当我在IE6和IE8中运行相同的代码时,两个回调都会被执行。这是我的抄写员中的一些错误,还是那些浏览器充满了这些错误之一? clearTimeout()/ clearInterval()是否保证在调用后不会调用回调?

Both timeout callbacks should prevent another another one from firing. In Opera, FF and Chrome only first one (that prints ″A fired″) is executed. But when I run the same code in IE6 and IE8, both callbacks are executed. Is that some error in my scriupt or is that one of those bugs that these browsers are full of? Do clearTimeout()/clearInterval() guarantee that callback won't be called after their invocation?

推荐答案

我认为发生了什么就是这样:

I think what is happening is that:


  • JavaScript有一个事件队列。

  • IE处理超时,并排队两个事件。

  • 处理第一个超时事件,并为B调用clearTimeout。但是B的事件已经排队,因此它仍然被触发。

  • 处理第二个超时事件,并为A调用clearTimeout。

  • JavaScript has an event queue.
  • IE processes the 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 gets fired.
  • the second timeout event is processed, and clearTimeout is called for A.

我怀疑在IE中,事件排队并且调用clearTimeout不会从事件队列中删除事件。

I suspect that in IE, the event gets queued and calling clearTimeout does not remove the event from the event queue.

IE也可能将同时超时推送到队列中的时间很短...诊断通过使用两个不同的超时,使用100%CPU处理循环x时间,以及通过在其他事件中排队/插入(可能是injec)可以实现潜在原因使用window.postMessage()将事件转移到队列中并使用window.onMessage())捕获它们。

It is also possible there is just funkyness in how IE pushes simultaneous timeouts onto the queue... Diagnosing the underlying cause could be acheived by using two different timeouts, using 100% CPU processing loops for x time, and by queuing/slotting in other events (maybe can inject events into queue using window.postMessage() and catch them with window.onMessage()).

我已修改现有代码以更好地演示问题。它将日志项排队而不是立即执行,因为调用display()会导致布局或呈现,这很容易引入其他时髦的干扰。

I have modified your existing code to demonstrate the problem better. It queues the log items rather than doing them immediately, because calling display() can cause layout or rendering to occur, which can easily introduce other funky interference.

编辑:你可以使用 http://jsbin.com/ucukez/2 进行测试 - 如果浏览器出现故障然后你得到在A超时解雇在B超时被解雇。

You can test this using http://jsbin.com/ucukez/2 - if the browser has the fault then you get "in A timeout fired" and "in B timeout fired".

编辑:这在IE9修复 - 我无法'在IE9 / IE10 / IE11中重现。

This was fixed in IE9 - I couldn't 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>

这篇关于澄清IE中的clearTimeout行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆