While debugging some client side javascript today in Firefox, I ran into something that I found quite odd and little unnerving. Also, I was unable to duplicate this behavior while debugging the same script with IE / VS2010.
I created a simple example html document to illustrate the anomally I am seeing.
<!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>
If you load this document into Firefox (I am using version 13.0 with Firebug version 1.10.1 on Windows 7), click test, and view the console tab in Firebug you should notice that the get request fails (cross domain violation that has nothing to do with the point I'm trying to make here), and then you will most likely see:
this will probably happen first.
this will probably happen second.
Now, place breakpoints on lines 13 and 20:
13: console && console.log && console.log("this will probably happen first.");
20: console && console.log && console.log("this will probably happen second.");
If you click test again you will break on line 13 as expected. Now, resume execution. If your experience is like mine, you will not break on line 20. Also if you switch to the console tab you will see the following sequence of log output:
this will probably happen second.
this will probably happen first.
To me, this suggests that the fail handler of the ajax request is being executed in a thread other than that which the click handler is being executed in. I have always been led to believe that all the javascript for a single page will be executed by a single thread in any browser. Am I missing something really obvious here? Thanks for any insight on this observation.
Oh, if I debug the same page running in IE using Visual Studio, both breakpoints are hit as I would expect.
I think it's safe to assume that the anomaly you're observing is caused by how Firebug implements breakpoints/works under the hood. I can't confirm that though. This also happens with FF 14 on OS X.
Unless jQuery immediately executes your fail() function and surpasses the whole XMLHttpRequest object, then there is a guarantee that the ordering of the statements will be this will probably happen first. then this will probably happen second..
Given the single threaded nature of JavaScript, functions will be essentially atomic; they will not get interrupted by a callback.
It seems as though you're trying to simulate what would happen if the click function takes a while to finish executing after calling loadStuff(). The click function shouldn't get interrupted by the fail method executing (mind == blown that you found a way to make that happen).
To take breakpoints out of the equation, here's a modified version. The rest of the markup is unchanged.
$(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.");
});
}
The click function clearly takes a long time to execute, after calling loadStuff(), but the console will still reflect the correct order of the log statements here. Also worth noting, if you insert the same breakpoints, the ordering will be invalid, like the original example.
I'd file an issue for this with Firebug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With