2

今天在 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 和 Firebug 版本 1.10.1),单击测试,然后在 Firebug 中查看控制台选项卡,您应该会注意到获取请求失败(跨域冲突,与做我要在这里提出的观点),然后你很可能会看到:

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 中运行的同一个页面,两个断点都会像我预期的那样被命中。

4

3 回答 3

2

我认为可以安全地假设您观察到的异常是由 Firebug 如何实现断点/在幕后工作引起的。不过我无法确认。OS X 上的 FF 14 也会发生这种情况。

除非 jQuery 立即执行您的fail()函数并超越整个XMLHttpRequest对象,否则可以保证语句的顺序将是this will probably happen first.then 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.");
        });
    }

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

我会向 Firebug提交一个问题

于 2012-08-03T21:37:54.260 回答
0

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

如果您需要在请求发出之前完成某些事情,请使用beforeSend()

于 2012-08-03T20:35:03.877 回答
0

根据我的经验,Firebug 在异步代码中放置断点时效果不佳。

即,如果您有一条直线执行并在其中放置断点,那么您会没事的。但是,如果您引入异步性,例如使用setTimeout,您将不会在“并行”行中遇到断点(这当然不是真正的并行,JS 引擎会在任务之间切换)。在过去的几个月里,我经历了很多。

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

重现问题的简单脚本:

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

<!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>
于 2012-08-06T19:46:28.283 回答