JavaScript的执行流程会被中断吗?

时间:2012-03-19 22:04:59

标签: javascript javascript-events concurrency

我一直认为,由于JavaScript是单线程的,我可以附加事件处理程序,而不必担心处理程序在执行代码时会被执行。令我惊讶的是,我发现他们可以。根据{{​​3}},“无响应脚本”对话框可能会导致在脚本仍在运行时引发事件

我使用以下代码对此进行了测试:

<script>
    function loop() {
        var cond;
        onblur = function (event) {
            cond = false;
        };
        cond = true;
        while (cond)
            ;
        alert('loop exited!');
    }
</script>
<button onclick="loop()">loop()</button>

this answer,

在Firefox 11.0中,该功能在单击“继续”后打印“循环退出”。循环似乎暂停,允许执行事件。这类似于暂时更改目标线程上下文的(jsFiddle)。但它更危险,因为它允许改变外部状态。

这是一个错误吗?我是否应该不再依赖JavaScript的单流执行模型并确保我的所有脚本都是可重入的?或者这是一个不值得追求的缺陷,尽管主要的浏览器允许这种情况发生?

2 个答案:

答案 0 :(得分:2)

所以是的,如果你创建一个无限循环,你将挂起你的JavaScript。差异浏览器将以不同的方式处理我的Firefox 11会抛出一个窗口,说明你的脚本已挂起。 Chrome目前正在为我旋转。

这应该证明了这一点。切勿在FF11或Chrome 17中拨打alert()

while(true){}
alert("sucks");

http://jsfiddle.net/JCKRt/1/

您询问了JavaScript中的同步语句。还有一些其他同步语句将阻止JavaScript的执行,如alert()confirm(),同步ajax调用等。

您通常希望避免使用JavaScript中的任何同步内容!如果您想要暂停,您可能需要重新考虑设计。 JavaScript是事件驱动的。你不需要它在while循环中旋转,因为页面上的没有可以工作,包括点击等任何事件。

答案 1 :(得分:0)

我认为当你开始处理事件时会出现问题。

不要使用while循环,而应考虑使用递归函数。

以下是我对您的代码所做的一些修改,应该根据需要执行。

<head>
    <script>
    function loop(that) {
        var cond;
        that.onblur = function (event) {
            cond = false;
        };
        cond = true;
        var loop = 0
        var xy = function x (){
            if(cond == true){
                loop++;         
                setTimeout(function(){xy()},0);
            } else {
                alert('loop exited! - '+loop);
                return true;
            }
        }
        xy();
    }
    </script>
</head>
<body>
    <button onclick="this.focus(); loop(this)">loop()</button>
</body>

使用带有0延迟的setTimeout()应该允许任何事件跳入而没有任何问题。你的循环代码不会被执行得那么快,你只需要测试它就可以看到。