今天在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中查看控制台选项卡,您应该注意到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中运行的同一页面,那么两个断点都会像我期望的那样被击中。
答案 0 :(得分:2)
我认为可以安全地假设您观察到的异常是由Firebug如何实现断点/工作引起的。我无法证实这一点。 OS 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.");
});
}
调用click
后,loadStuff()
函数显然需要很长时间才能执行,但控制台仍会在此处反映日志语句的正确顺序。另外值得注意的是,如果插入相同的断点,则排序将无效,就像原始示例一样。
我和Firebug一起file an issue。
答案 1 :(得分:0)
$.get("http://google.com/")
是异步的,它是对首先完成的事情的竞赛。第一次它变慢,因为它需要进行调用,并且调用稍后在代码执行中发生。该调用已经缓存了第二个请求,因此它更快地执行。
如果您在请求结束前需要完成某些操作,请使用beforeSend()。
答案 2 :(得分:0)
根据我的经验,在异步代码中放置断点时,Firebug无法正常工作。
即。如果你有一条直线执行并在其中加入断点,你会没事的。但是,如果你引入异步性,例如通过使用setTimeout
,您将不会在“并行”行中遇到断点(当然,这不是并行的,JS引擎在任务之间切换)。我在过去几个月里经历过很多次。
在Chrome中,它似乎工作正常(它们以某种方式智能地延迟超时)。也许是因为Chrome开发工具内置于浏览器中,因此操作超时更容易。 Firebug“只是”一个附加组件,也许正确地执行它可能很棘手。
重现问题的简单脚本:
当我将值分配给x
,y
,z
时,将断点放在行中。
首先,您将在x = 1
行上找到一个断点。使用 F10 跳过。只有当你按 F10足够快时,你<{1>} 1}} 1>} 1>}上的将不会遇到断点(Firefox 14,Firebug 1.10)。
z = 3