In a recent blog entry, “The Hardware of Tomorrow Versus the Platform of Tomorrow”, Joe Walker raised some important Ajax issues. He talks about the increasing multiprocessing capabilities of today’s hardware, and web browsers’ inability to take full advantage of it.
He mixes two separate issues, talking about the lack of threading/concurrency support in the Javascript language, and also the lack of multi-threading within web browsers.
It’s this second issue that I want to explore here, particularly this comment:
“The problem is that web-browsers are a step backwards as far as multi-threading goes. In Javascript there is no such thing as a new thread, and worse than that, the entire platform (i.e. a browser) runs a single JavaScript thread. If a script in one window goes into a tight loop, or runs some synchronous Ajax then the browser HTML display freezes.”
Hmmm. That last sentence started gnawing at me. I’ll leave the “tight loop” problem for another day, but is it true that a synchronous XMLHttpRequest call will “freeze” the browser?
If Joe means that the page making the synchronous call freezes, I’ll agree. If it’s a synchronous, or blocking call, then nothing will happen within the page until it completes. We shouldn’t expect anything else. That’s what blocking I/O does.
But the earlier sentence implies that all browser windows (or tabs) will freeze during a sync call (“…the entire platform (i.e. a browser) runs a single JavaScript thread”). Is that true?
I wasn’t sure, but I knew how to find out.
A Simple Experiment
I wrote two programs. The first would run a single synchronous call to my web server. It calls a
tiny Perl server program that sends back a string like this:
Server: received at 21:19.14, replied at 21:19.17 (requested delay 3)
The server program accepts a single parameter, wait. The server program then waits the specifed number of seconds before replying. In the example above, the Ajax call
requested a 3 second delay.
The second program launches five asynchronous calls. They call the same server program. I can set each async call with a separate server delay time.
[This second program is described in more detail in an earlier blog entry here.]
For my experiment, I open up a browser window, then open a second browser window using the “New Window” menu option. This will (hopefully) assure that both windows are part of the
same browser process.
In window #1, I load my synchronous test and start a server request with a delay of 60 seconds. In window #2, I load the asynchronous test with each of the five tests set to three seconds.
The hypothesis is:
After launching the synchronous call, other browser windows or tabs will be frozen, and the asynchronous calls will not be serviced until the sync call completes.
Test Results
I tested with three different browsers on two different OSs. Here were my results:
| Browser | Sync Call Freezes Browser |
|---|---|
| Firefox 2.0.0.1 on Linux | yes |
| Firefox 2.0.0.1 on Windows XP | yes |
| Opera 9.10 on Linux | no |
| MS Internet Explorer 6.0 on Windows XP | no |
For Internet Explorer and Opera, the results were essentially the same. Other windows/tabs did not freeze, and the asynchronous calls were all launched and completed while the
60 second synchronous call was still waiting for its server response.
The screenshot below shows the Opera test, with the synchronous test in the top window and the async test below. You can see that the sync request was received a second before the asyncs started, and that all the asyncs completed while the synchronous request was still pending.

On Firefox, all browser windows ceased responding to any events until the synchronous call completed.
For IE and Opera, this means that each browser window’s Javascript has some degree of independence from other windows. A synchronous call in one window won’t block another window’s processing.
Unfortunately, if you’re writing web apps that act consistently across all the major browsers, this means you’ll need to assume the browser will freeze on synchronous calls. So in that sense, Joe is correct.
I haven’t looked at the underlying Firefox code, so I don’t know how hard this problem will be for them to remedy. But Opera and IE seem to have tackled it successfully.

This is really interesting, Mark. Thanks for the data (and the work that went into gathering it)!
An Update: Since posting, I've read that the sync-freezing problem is resolved in Moz/Firefox nightly builds. I downloaded the trunk build for Linux (Firefox Minefield/3.0a2pre) and ran my tests. Sure enough -- no more freeze! So it looks like this problem will be history for all major browsers with the next Firefox release.
thank god, i am waiting for firefox to release the updates.... in one of my projects i needed to make sync call but as it freezes the firefox i had to look for lengthy way to handle this situation... :(
I quite often experience Firefox freezes (I'm currently on 1.5.0.9); experience has taught me to associate them with certain sites and/or conditions, which I now tend to avoid when possible. I find it quite frustrating that the entire app hangs while waiting on one tab/connection.
For the IE test, make sure you have multiple windows in a single process.
Starting IE from a shortcut or command line starts a new process, while using "new window" within the IE window runs the second window in the same process.
This may affect your results.
Seems that some messages just aren't getting through. Been banging this drum since May 2005. A demo: http://www.phppatterns.com/stuff/sync.html
Otherwise ... http://www.sitepoint.com/blogs/2006/02/10/ajaxlocalhost/
Hello Mark - I hope you can explore this a little further. If you read my posts at http://forums.asp.net/thread/1470419.aspx regarding a similar issue with javascript you will notice synchronous calls will break thread safety in javascript. I believe the same bug you describe as fixed in a development build of Firefox was responsible for maintaining safety of data and IE and Opera do not block synchronous calls properly.
The reason why your synchronous calls should be frozen across browsers within the same process is to make sure that concurrency issues to do arise. If this is "fixed" then I think there will be more problems. After all a synchronous call should block all further execution until it is returned.
I realize your example does not use child windows but you simply did an Open New Window but you can understand the need for proper fix here. Windows that do not have any children or parents should not block other windows. However, windows with parents and/or children should definitely be blocking calls.
My 2 cents.
Er, does anyone really still use synchronous xmlhttprequest calls? They seem rather pointless in JS to me.
Thanks, this is quite informative. I also find it very motivating when someone reminds me about not to take anything for granted and to look out for the facts behind the speech.
On need of doing synchronous calls, I think that if a developer ends up in a situation in which he needs synchronous call, he'd better think again because he whould have completely missed the point of Asynchronous JavaScript and XML.
As a user, what I hate the most is when my user interface freezes. Coding asynchronously is harder and a little more work, but at the end it is worthwhile for the user experience. If you need data, say it to the user, if you need to wait for the result of an action before being able to allow a new one, disable the buttons or links, and say it.
You cannot ensure concurrency by "freezing" the page, or even the application. What if, because you froze the firefox of your user, he opens an Internet Explorer to continue working and ends up doing the exact action you wanted to prevent ?
"On need of doing synchronous calls, I think that if a developer ends up in a situation in which he needs synchronous call, he'd better think again because he whould have completely missed the point of Asynchronous JavaScript and XML. As a user, what I hate the most is when my user interface freezes."
Vincent,
I agree 100% that synchronous calls should be avoided. But if you do use them, you should know how they'll affect browsers. I'd read that sync calls froze browsers, but didn't recall that being true for Opera. I guess my big unspoken point in all of this was: When in doubt, experiment.
This is why I really appreciate your post.
It will be interesting if you repeat this experiment with two frames instead of two windows.
I find that Opera 9 allows interaction with user and between frames even if one of frames is busy in endless loop, while IE 6 and FF 1.5 doesn't. This experiment didn't involve XMLHttpRequest.
anyone mind sharing a cross-browser version (FF+IE) of a synchronous ajax call that actually works? thanks!
John - Use a Javascript toolkit like Dojo:
dojo.io.bind({ url: '/test.php' });
Oops - you wanted synchronous:
dojo.io.bind({ url: '/test.php', sync: true });
John,
This code has worked well for me for creating a cross-browser XMLHttpRequest object. Is there something beyond this (related to sync calls) that's causing a problem?
//----------------------------------------------------------
// Browser-neutral creation of an XMLHttpRequest object.
//----------------------------------------------------------
function getHTTPObject() {
var xmlhttp;
/*@cc_on
@if (@_jscript_version >= 5)
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
xmlhttp = false;
}
}
@else
xmlhttp = false;
@end @*/
if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
try {
xmlhttp = new XMLHttpRequest();
} catch (e) {
xmlhttp = false;
}
}
return xmlhttp;
}