firebug(1.10.1)建议javascript不局限于firefox(13.0)中的单个线程

firebug (1.10.1) suggests javascript is not confined to a single thread in firefox (13.0)

本文关键字:单个 线程 建议 javascript firebug 局限于 firefox      更新时间:2023-09-26

今天在Firefox中调试一些客户端javascript时,我遇到了一些奇怪且有点令人不安的事情。此外,在使用IE/VS2010调试同一脚本时,我无法复制此行为。

我创建了一个简单的html文档示例来说明我所看到的异常情况。

<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.js" type="text/javascript" ></script>
</head>
<body id="main_body">
    <script type="text/javascript">
        $(function () {
            $(".test-trigger").on("click", function () {
                loadStuff();
                console && console.log && console.log("this will probably happen first.");
            });
        });
        function loadStuff() {
            $.get("http://google.com/")
                .fail(function () {
                    console && console.log && console.log("this will probably happen second.");
                });
            }
    </script>
    <button class="test-trigger">test</button>
</body>
</html>

如果你将此文档加载到Firefox中(我在Windows 7上使用的是13.0版本和1.10.1版本的Firebug),点击测试,并在Firebug中查看控制台选项卡,你应该注意到get请求失败了(跨域违规与我在这里试图提出的观点无关),然后你很可能会看到:

this will probably happen first.
this will probably happen second.

现在,在第13行和第20行放置断点:

13: console && console.log && console.log("this will probably happen first.");
20: console && console.log && console.log("this will probably happen second.");

如果您再次单击"测试",您将按预期在第13行中断。现在,继续执行。如果你的经验和我一样,你就不会在20号线上崩溃。此外,如果您切换到控制台选项卡,您将看到以下日志输出序列:

this will probably happen second.
this will probably happen first.

对我来说,这表明ajax请求的失败处理程序是在一个线程中执行的,而不是在点击处理程序中执行的。我一直相信,在任何浏览器中,单个页面的所有javascript都将由单个线程执行。我是不是错过了一些显而易见的东西?感谢您对这一观察的任何见解。

哦,如果我使用Visual Studio调试在IE中运行的同一个页面,两个断点都会像我预期的那样被命中。

我认为可以安全地假设您观察到的异常是由Firebug如何在后台实现断点/工作引起的。不过我不能证实。这也发生在操作系统X上的FF 14上。

除非jQuery立即执行fail()函数并超越整个XMLHttpRequest对象,否则可以保证语句的顺序是this will probably happen first.然后是this will probably happen second.

考虑到JavaScript的单线程性质,函数本质上将是原子的;它们不会被回调所打断。

似乎您正在尝试模拟如果click函数在调用loadStuff()后需要一段时间才能完成执行,会发生什么。click函数不应该被fail方法的执行所中断(记住你找到了实现这一点的方法)。

为了去掉等式中的断点,这里有一个修改后的版本。标记的其余部分保持不变。

$(function () {
    $(".test-trigger").on("click", function () {
        loadStuff();
        for (var i = 0; i < 1000000000; i++)
        {
            //block for some interesting calculation or something
        }
        console && console.log && console.log("this will probably happen first.");
    });
});
function loadStuff() {
    $.get("http://google.com/")
        .fail(function () {
            console && console.log && console.log("this will probably happen second.");
        });
    }

调用loadStuff()后,click函数显然需要很长时间才能执行,但控制台仍会在此处反映日志语句的正确顺序。同样值得注意的是,如果插入相同的断点,则排序将无效,就像最初的示例一样。

我会向Firebug提交一个问题。

$.get("http://google.com/")是异步的,它是一场关于先完成什么的竞赛。第一次它的速度较慢,因为它需要进行调用,而调用发生在代码执行的后期。该调用已经与第二个请求一起缓存,因此它的执行速度更快。

如果在请求发出之前需要做一些事情,请使用beforeEnd()。

根据我的经验,在异步代码中设置断点时,Firebug不能很好地工作。

也就是说,如果你有一条直线执行,并在其中设置断点,你就可以了。然而,如果引入异步性,例如使用setTimeout,则不会在"并行"行中遇到断点(当然,这实际上不是并行的,JS引擎在任务之间切换)。在过去的几个月里,我经历了很多。

在Chrome中,它似乎运行良好(它们以某种方式智能地推迟超时)。也许是因为浏览器内置了Chrome开发工具,所以操作超时更容易。Firebug"只是"一个附加组件,也许要正确执行它可能很棘手。

一个简单的脚本来重现问题:

当我为xyz赋值时,在行中放置断点。首先,您将在x = 1行上遇到一个断点。使用F10进行跨步操作。您不会在带有z = 3的行上遇到断点,只有在您足够快地按下F10(Firefox 14,Firebug 1.10)时才会在带有z = 3的行上碰到断点。

<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
function foo(){
   var x = 1;
   setTimeout(bar, 2000);
   var y = 2;
}
function bar(){
   var z = 3;
}
foo();
</script>
</body>
</html>