Newbie Q: XMLHttpRequest.send() and race conditions?

K

kj

Hi. I'm new to programming with XMLHttpRequest and I'm unclear
about how non-blocking requests are handled, and in particular
about the question of the potential for race conditions. Suppose
that I have a function like this one that gets called when, for
example, the user clicks some button X:

function handleButtonXClick() {
var request = makeRequest();
function handleResponse() {
if ( request.readyState == 4 && request.status == 200 ) {
// has its way with some Innocent Global Variables...
}
};
request.onreadystatechange = handleResponse;
var url = 'http://myurl.com/cgi/latestinfo';
request.open( 'GET', url ); // non-blocking request, asynchronous response
request.send();
}

My question is: if the user triggers two invocations of handleResponse
in rapid succession, could the second invocation begin before the
first one is finished? Or does the browser ensure that these two
invocations are executed sequentially?

Assuming that the browser allows both invocations to execute
concurrently, does JavaScript provide any mechanism for locking
shared resources, such as global variables?

(I know that I could design the UI to prevent concurrent requests,
e.g. by disabling button X until handleResponse finishes, but I
would like to avoid this if I can.)

Thanks!

kj
 
W

webEater

kj said:
Hi. I'm new to programming with XMLHttpRequest and I'm unclear
about how non-blocking requests are handled, and in particular
about the question of the potential for race conditions. Suppose
that I have a function like this one that gets called when, for
example, the user clicks some button X:

function handleButtonXClick() {
var request = makeRequest();
function handleResponse() {
if ( request.readyState == 4 && request.status == 200 ) {
// has its way with some Innocent Global Variables...
}
};
request.onreadystatechange = handleResponse;
var url = 'http://myurl.com/cgi/latestinfo';
request.open( 'GET', url ); // non-blocking request, asynchronous response
request.send();
}

My question is: if the user triggers two invocations of handleResponse
in rapid succession, could the second invocation begin before the
first one is finished? Or does the browser ensure that these two
invocations are executed sequentially?

Assuming that the browser allows both invocations to execute
concurrently, does JavaScript provide any mechanism for locking
shared resources, such as global variables?

(I know that I could design the UI to prevent concurrent requests,
e.g. by disabling button X until handleResponse finishes, but I
would like to avoid this if I can.)

Thanks!

kj

What you do will not work, you must set the 3rd param for open method
in firefox, true means asynchronous, false means synchronous request,
so use true (the A in Ajax)

request.open( 'GET', url, true); // non-blocking request, asynchronous
response
request.send(null);

param in send method must be null.

Andi
 
K

kj

In said:
What you do will not work, you must set the 3rd param for open method
in firefox, true means asynchronous, false means synchronous request,
so use true (the A in Ajax)
request.open( 'GET', url, true); // non-blocking request, asynchronous
response
request.send(null);
param in send method must be null.

Thanks, but those details were not the point of my question. The
main question remains: can multiple invocations of the onreadystatechange
handler happen concurrently, or does the browser make sure that
they happen sequentially?

Thanks,

kj
 
L

Laurent Bugnion

Hi,
Hi. I'm new to programming with XMLHttpRequest and I'm unclear
about how non-blocking requests are handled, and in particular
about the question of the potential for race conditions. Suppose
that I have a function like this one that gets called when, for
example, the user clicks some button X:

function handleButtonXClick() {
var request = makeRequest();
function handleResponse() {
if ( request.readyState == 4 && request.status == 200 ) {
// has its way with some Innocent Global Variables...
}
};
request.onreadystatechange = handleResponse;
var url = 'http://myurl.com/cgi/latestinfo';
request.open( 'GET', url ); // non-blocking request, asynchronous response
request.send();
}

My question is: if the user triggers two invocations of handleResponse
in rapid succession, could the second invocation begin before the
first one is finished? Or does the browser ensure that these two
invocations are executed sequentially?

The invocation will be executed sequentially (JavaScript is single
threaded), but the browser doesn't check if a request is currently
active before sending a next one. That would be very inefficient, and
would lose all the benefits of asynchrnous requests.

If you need to make sure that a request ends before another is sent, you
can either use synchronous calls (but they are blocking, so not a good
idea), or use a "isRequestActive" variable, which prevents a new request
being sent as long as the response didn't arrive. Set the variable to
true before the "send" call, set it to false in "handleResponse" (also
in error cases).

Additionally, it might be a good idea to enclose your code in try/catch,
and set the varable to false in the catch (so that a possible error
doesn't prevent sending again.

One more thing: The current HTTP stack implementation prevents more than
2 connections being open concurrently from a give client to a given web
server. So you have a maximum of 2 concurrent XmlHttpRequests to a given
web server at any time (but that doesn't help you in your case, 2 being
too much anyway ;-)

Assuming that the browser allows both invocations to execute
concurrently, does JavaScript provide any mechanism for locking
shared resources, such as global variables?

No, such mechanism (lock) doesn't exist in JavaScript, as JavaScript is
single threaded and doesn't need this. But requests sent asynchronously
are a special case, and need an implementation as described above.
(I know that I could design the UI to prevent concurrent requests,
e.g. by disabling button X until handleResponse finishes, but I
would like to avoid this if I can.)

That would be a good practice anyway (but doesn't prevent you from
implementing a safeguard).
Thanks!

kj

HTH,
Laurent
 
W

webEater

What you do will not work, you must set the 3rd param for open method
in firefox, true means asynchronous, false means synchronous request,

I quote myself, I answered your question - this is what I wanted to
explain you, the third param makes the difference. Default is true.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,821
Latest member
AleidaSchi

Latest Threads

Top