Synchronous v. Asynchronous
April 4, 2006 at 11:55 am by Douglas Crockford | In Development |XMLHttpRequest can operate synchronously or asynchronously. Many people prefer to use it synchronously. When used this way, the JavaScript engine is blocked until the interaction with the server is complete. Because it blocks, the flow of control looks a lot like an ordinary function invocation. Temporal complexity is abstracted away, leaving a very familiar and comfortable programming pattern. It works particularly well when the server is on the same machine, or nearby on the LAN. Unfortunately, it can perform very badly if the server is under heavy load, or if the browser is connected to the server over a slow link. Because the JavaScript engine is blocked until the request completes, the browser will be frozen. The user cannot cancel the request, cannot click away, cannot go to another tab. This is extremely bad behavior.
Fortunately, XMLHttpRequest provides an option for asynchronous operation. When you set the asyncFlag flag to true, the JavaScript engine does not block. Instead the request returns immediately, with a potential action that will be triggered later when the result on the request is known. The Yahoo! Connection Manager provides a very nice interface for this.
var cObj = YAHOO.util.Connect.asyncRequest('GET', 'http://myservice.com?req=update', {
success: function (response) {
alert(response.responseText);
},
failure: function (response) {
alert(response.statusText);
}
});
You supply two functions. Your success function contains everything that should happen as a result of the request succeeding. So if the request was to obtain some JSON text which should be delivered to the app.update method, then your success function could be
success: function (response) {
app.update(eval('(' + response.statusText + ')'));
}
Asynchronous programming is slightly more complicated because the consequence of making a request is encapsulated in a function instead of following the request statement. But the realtime behavior that the user experiences can be significantly better because they will not see a sluggish server or sluggish network cause the browser to act as though it had crashed. Synchronous programming is disrespectful and should not be employed in applications which are used by people.
Share and extend: Bookmark with Yahoo! My Web | Bookmark with del.icio.us | digg it! | reddit!
22 Comments »
RSS feed for comments on this post. TrackBack URI
Leave a comment

Copyright © 2007 Yahoo! Inc. All rights reserved. Privacy Policy - Terms of Service
Powered by WordPress on Yahoo! Web Hosting.
But there’s one big problem with asynchronous XMLHttpRequest. What if there is more than one pending async call but the responses “return” in a different order than the requests were sent? It isn’t hard to think of an example. For instance, I may have a select for states which onselect send an async message to obtain a list of cities. A user may select “California”, then quickly select “Colorado”. However, the list of Colorado’s cities may return before California’s. Depending on the technique used to display the list of cities, the user may see California’s cities but hae Colorado selected.
I know this can be handled to some degree by using various techniques to order responses (a sequence sent on a request returned by the response), queuing, etc… but I think these solutions only work if the state of the page is orthogonal to that returned by the response to the XMLHttpRequest…
Comment by Ted — April 4, 2006 #
To Sync or not to Sync!…
The Yahoo! UI Blog shares how to use XMLHttpRequest in a sort of pseudo-multithreaded and event-oriented fashion. My favorite quote: “Synchronous programming is disrespectful and should not be employed in applications which are used by people.”…
Trackback by AJAXGallery.Net — April 4, 2006 #
I often lamented back in the day that Javascript doesn’t have a non-blocking sleep() method. That’s all it would take to launch an async call and then wait for evidence of its completion before continuing from where you made the call without losing context.
Quite a few early XMLHttp code implementations used a tight loop waiting for readystate==4, which caused similar browser lockups.
But then I just sucked it up and learned to deal with asynchronous event-driven programming.
Comment by Brent Ashley — April 5, 2006 #
Ted, theres 2 ways round this that I can think of:
1. Disable the select when a user selects something, and diplay a “getting/loading” message. It remains disabled until the request returns.
2. Id the request in the browser and send that id as part of the request, when the request returns it checks if the returned id matches the currently set id in the browser. If they dont match then it means your scenario has occurred and the results should not be displayed. If they do match then its ok to display the results.
Comment by Tim — April 5, 2006 #
To deal with the async requests coming back in a different order you don’t even need to change the server so that it returns some request id. You can either wrap your XMLHttpRequest object with a custom class that has the id as a property on it. Then a reference to this wrapping class can be passed as a parameter to you success / failure method. If you really want you can even just set the id property right on the XMLHttpRequest object - that just makes it harder for programmers to understand :)
Comment by dave johnson — April 15, 2006 #
I’ve used Dave’s technique with Math.random() as the generator of the request id. As the requests complete, I compare their ids to the most recent id, ignoring those which do not match.
To get really crazy you could add a timer to front of the id approach. Using window.setInterval, wait X milliseconds before making the request. If a new request arrives during the interval you can drop the request. This adds the benefit that if the user makes several rapid UI changes it does not hammer the server.
Comment by brandon beacher — April 25, 2006 #
I understand the various ways to handle ordering issues with regards to async requests… but I think it’s a wrinkle that makes AJAX programming considerably trickier. It’s like going from code where you can assume a single thread to writing multi-threaded code. Suddenly, it seems like you have to have a different level of ability in the person writing the code…
Comment by Ted — May 1, 2006 #
In the last example of the “success” function, shouldn’t it be response.responseText rather than response.statusText?
Also, for failures, is there some sort of timeout? A cool feature would be the ability to set a timeout, like 10 seconds, after which the request automatically assumes a failure.
Comment by Idris — May 2, 2006 #
Ted,
Your point is valid. Some people discussed adding an ID attribute to requests. This is a decent solution, as long as you keep it in connection headers, as it really has no business being in the XML response body.
Another solution is one I presented in an article on DevX about a year ago:
http://www.devx.com/webdev/Article/28695
In this case, your code doesn’t care about order or even the global structure of the XML response body. Handlers are “attached” to XML nodes and the handler is fired whenever that XML node is encountered in an XML response body. An example might be a node named chat-msg, which gets passed to a function called appendChatMsg(node) each time the node is encountered.
This way, your app is not concerned with the communication that is happening. Instead, different components of your application respond to new relevant data when it arrives.
Hope this helps.
Comment by mwarden — May 14, 2006 #
“But there’s one big problem with asynchronous XMLHttpRequest. What if there is more than one pending async call but the responses “return” in a different order than the requests were sent?”
The problem is not just order in which responses return - you could also get requests arriving out of order at the server. If the requests correspond to something changing / being stored on the server and the sequence they arrive is used implicitly when making that change (e.g. appending messages to a chat file), you also have a problem - the server also needs to “think” about ordering. Tried to illustrate those problems here.
Attaching IDs / sequence numbers to requests can help although it will generally be application specific and in the client to server direction, needs care (what if ID 3 and 5 arrive at the server but 4 somehow vanishes - what should the server do - how much state should it maintain to keep track of this?).
Another approach is simply don’t let the client send more than one request at a time. To help mitigate performance issues, “boxcarring” multiple payloads into a single request can help.
Comment by Harry Fuecks — May 19, 2006 #
This is opinionated software, but I offer the opinion is wrong.
The Yahoo UI libraries should, as a first order of business, abstract the supported base objects as the de facto implementations deliver them. These base functions support synchronous requests. If you do not like this, lobby the w3 and the browser vendors. They will also tell you that you are wrong coincidentally.
To simply state that “synchronous programming is disrespectful” is cute but pointless and furthermore wrong. You do not know my use case.
Now to use these libraries to implement a viable use case for synchronous coding I am forced to introduce laborious and error prone hacks. I will likely just use Dojo instead, its developers are not interested in judging my requirements.
Comment by brad — June 5, 2006 #
brad–
Your use case is one where you’d sacrifice usability over making part of the code slightly easier?
Yahoo! has every right to steer people in any direction they wish with THEIR libraries. The code is licensed in a manner such that you can trivially modify it, if you wish. The XMLHttpRequest object itself is a fairly minimal amount of code; something you could easily implement yourself if you don’t wish to use the YUI libraries.
The level of arrogance involved in telling Y! what they should and shouldn’t be implementing in giving away a set of open source JS libraries is a little astounding.
Comment by Mo — June 8, 2006 #
Javascript and Ajax Items for Discussion…
Items n links Libs…
Trackback by Confluence: Development Services Group — June 23, 2006 #
[TRM-1108] Remove Synchronous Ajax calls from Seg SelectionDatasources.js…
Synchronous Ajax calls lock the browser. If for some reason the request did not return, the only way to unlock the browser is to kill it from Task Manager. Sync calls are not considered good programming form. And dont take it from me, here is a blog o….
Trackback by JIRA: Teradata Relationship Manager — February 2, 2007 #
[…] Synchronous v. Asynchronous […]
Pingback by ajax-tr.com » Asenkron ve Senkron Meselesi — February 3, 2007 #
Wow, Yahoo! Connection Manager looks like Prototype ;-)
Actually I like prototype. Also Scriptaculous uses it.
Comment by Alexey Epishkin — May 4, 2007 #
Dealing with multiple request (like the colorado example give) is really not terribly difficult.
My solution was to track the XMLHttpRequest object in a variable (we’ll call it xhr).
When an attempt to make a new Ajax call is made I check xhr to see if it is null. If it is not I call xhr.abort() to kill the request (now it will not return, out of order or otherwise). Then I set xhr = null and make the new request storing the new XMLHttpRequest object in xhr.
var xhr = null;function MakeAjaxCall() {
if (xhr !== null) {
xhr.abort();
xhr = null;
}
xhr = new XMLHttpRequest(/* proper settings */);
/* more code to complete the XMLHttpRequest */
}
I also add a delay when making Ajax requests from a UI component. This gives the user a tiny moment to cycle through selects without my code making and aborting a lot of Ajax calls.
var select_change_timeout = null;var reasonable_delay = 100; // or something reasonable
var select_element = document.getElementById("my_select_element");
select_element.onchange = function () {
if (select_change_timeout !== null) {
clearTimeout(select_change_timeout);
select_change_timeout = null;
}
select_change_timeout = setTimeout(MakeAjaxCall, reasonable_delay);
};
Disclaimer: code samples are simplified and untested and may not work for you.
Comment by Jake — May 11, 2007 #
[…] @ http://yuiblog.com/blog/2006/04/04/synchronous-v-asynchronous/ var addthis_pub = ‘codelinkers’; Back to Codelinkers your virtual Link Sharing […]
Pingback by Synchronous v. Asynchronous | codelinkers — May 23, 2007 #
A valid use for a synchronous call: requests made onunload.
For example, you have a database application with a list view and a record view. Records are locked when loaded and unlocked when unloaded. The locking can be done server-side, but the unlocking needs to be done via a JavaScript request.
By the time the request is complete the page is gone. If there was a callback function, it’s gone. If the loading of the next page is affected by the lock status, there is no guarantee that the XMLHttpRequest is finished before it starts loading. You can’t just put the unlock function on the list page, or in the link, because you don’t know what the user is clicking on or if they might want to have two records open.
Comment by Billy — May 29, 2007 #
Ted
While you have a valid point, I disagree that current behavior of XMLHttpRequest is a problem or faulty design. A true async operation should return when the operation is finished. It shouldn’t have dependency on when the operation is invoked.
Previous comments has shown that it is easy to cope with the async behavior to achieve your goal. But if XMLHttpRequest is designed to have response return in invocation order, it will be very difficult to achieve true async operation, therefore make it useless on many other use cases.
Comment by Rushui — August 23, 2007 #
pan tractor seats the radio station for 933 fm olivia cruises & resorts performers fox news corporate phone numbers baldwin police blotter adventure city buena park white orelander minimum gpa for transfer to suny cortland horizon foods win back the one you love
Comment by feechka-no — February 20, 2008 #
Here’s my synchronous use case: Before I respond to any of my 50 possible ajax gestures that depend on the user being logged in, I need to verify that the user is, in fact, still logged in - that there hasn’t been a session time-out. If the session is timed out, and I no longer know who’s logged in, I need to redirect to a log-in page (or some such action); otherwise, I proceed to fulfill the request for the logged in user.
I do this with a simple javascript call, separate from the ajax call - I don’t modify all my ajax request handlers to do their own checking for member login, and their own event handling (in the success function) if the member is not logged in.
I currently have a home-grown synchronous ajax call to check for logged-in-ness that I use before initiating the specific ajax action. I was hoping to drop the home-grown stuff and just use YUI - but it appears I can’t, since YUI doesn’t support synchonous calls. Is there some better YUI way to handle this use case?
Comment by Glen — April 22, 2008 #