XMLHttpRequest.onreadystatechange Method Not Running

H

HugeBob

Hi All,

I'm having a problem with a web app I'm writing. I have a form for
which I'm going to validate one of the fields. I use AJAX to retrieve
XML containing a list of valid entries. My app works under IE, oddly
enough. But, under Firefox, it seems that the
XMLHttpRequest.onreadystatechange method is not being called. The
code follows. I'm using synchronous mode because I'm thinking that I
want that global variable g_groupListXML to contain
xmlHttp.responseText before ajaxGetGroupUserListXML( ) returns. Am I
right on this point?

function getXMLHTTPRequestObject( )
{
var xmlHttp = null;
try
{
// Firefox, Opera 8.0+, Safari
xmlHttp = new XMLHttpRequest();
}
catch (e)
{
// Internet Explorer
try
{
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try
{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e)
{
alert("Your browser does not support AJAX!");
}
}
}
return xmlHttp;
}


var g_groupListXML = null;

function ajaxGetGroupUserListXML(url)
{
var xmlHttp = null;
xmlHttp = getXMLHTTPRequestObject( );
xmlHttp.onreadystatechange = function ()
{
if
(xmlHttp.readyState == 4)
{

alert("onreadystatechange called...");

g_groupListXML = xmlHttp.responseText;
}
}
xmlHttp.open("GET", url, false);
xmlHttp.send(null);
}

function getGroupListXML(form)
{
var retval = false;
var xmlDoc = null;
var doc = null;

ajaxGetGroupUserListXML('XMLProducingScript.cfm');

// Parse retrieved XML
if (window.ActiveXObject)
{
doc = new ActiveXObject("Microsoft.XMLDOM");
doc.async = "false";
doc.loadXML(g_groupListXML);
}
else
{
var parser = new DOMParser( );
doc = parser.parseFromString(g_groupListXML, "text/xml");
}

xmlDoc = doc.documentElement;
form.fieldx.value = trim(form.fieldx.value);

for (var i = 0; i < xmlDoc.childNodes.length; i++)
{
if (xmlDoc.childNodes.childNodes[0].nodeValue.toLower( ) ==
form.group_name.value.toLowerCase())
{
alert('String already used');
retval = true;
break;
}
}
return retval;
}
 
I

Ian Collins

HugeBob said:
Hi All,

I'm having a problem with a web app I'm writing. I have a form for
which I'm going to validate one of the fields. I use AJAX to retrieve
XML containing a list of valid entries. My app works under IE, oddly
enough. But, under Firefox, it seems that the
XMLHttpRequest.onreadystatechange method is not being called. The
code follows. I'm using synchronous mode because I'm thinking that I
want that global variable g_groupListXML to contain
xmlHttp.responseText before ajaxGetGroupUserListXML( ) returns. Am I
right on this point?
You don't have to bother with onreadystatechange if you make a
synchronous request, just use the responseXML/Text.
 
I

Ian Collins

-Lost said:
Um, if you have to make synchronous calls you need to rethink your AJAX.
Not if it's a call to get information required to carry on, loading an
interface description for example.
 
L

-Lost

Ian Collins said:
Not if it's a call to get information required to carry on, loading an
interface description for example.

Very good point! However, causing the UA to block until that information is retrieved is
erroneous.

You can achieve much more efficient results by using an asynchronous call (I mean, come
on, AJAX). Storing the responseText for example, then displaying it where and if, need
be.

In fact, the responseText is normally only available at a readyState of 4, so... I do not
see the *need* of synchronous calls.

-Lost
 
I

Ian Collins

-Lost said:
Very good point! However, causing the UA to block until that information is retrieved is
erroneous.

You can achieve much more efficient results by using an asynchronous call (I mean, come
on, AJAX). Storing the responseText for example, then displaying it where and if, need
be.
It's a tricky problem if you have to set up some preconditions (such as
building an RPC object from a description file) before the AJAX
functionality on the page can be used. You have three choices:

1) Use a synchronous request.
2) Poll to see if the preconditions have occurred.
3) trap the error if an AJAX call is made before the the preconditions
have occurred.

Which you choose probably depends on the environment, I mainly support
intranet applications, so I can take the easy first option.
 
L

-Lost

Ian Collins said:
It's a tricky problem if you have to set up some preconditions (such as
building an RPC object from a description file) before the AJAX
functionality on the page can be used. You have three choices:

1) Use a synchronous request.
2) Poll to see if the preconditions have occurred.
3) trap the error if an AJAX call is made before the the preconditions
have occurred.

1. Based on your intranet usage, this is ideal.

2. No need to poll when using asynchronous calls. As the readyState will update you
regardless of async or sync.

3. You can however use e.target.status if the AJAX returns erronous results based upon
the context of theXMLHttpRequest.

Example:

function onError(e)
{
alert(e.target.status);
}
XMLHttpRequest.onerror = onError; // assuming XMLHttpRequest is a valid XHR Object
Which you choose probably depends on the environment, I mainly support
intranet applications, so I can take the easy first option.

Ah hah! So the implementation defines the use!

Even in an intranet application I would be hard-pressed to not use async calls. However,
I have used synchronous calls based on the fact an intranet application should have
instantaneous results.

-Lost
 
R

Richard Maher

Hi Ian, Lost

-Lost said:
1. Based on your intranet usage, this is ideal.

2. No need to poll when using asynchronous calls. As the readyState will update you
regardless of async or sync.

3. You can however use e.target.status if the AJAX returns erronous results based upon
the context of theXMLHttpRequest.

Example:

function onError(e)
{
alert(e.target.status);
}
XMLHttpRequest.onerror = onError; // assuming XMLHttpRequest is a valid XHR Object


Ah hah! So the implementation defines the use!

Even in an intranet application I would be hard-pressed to not use async calls. However,
I have used synchronous calls based on the fact an intranet application should have
instantaneous results.

-Lost

-Lost, you don't seem to mention any downside or additional
processing/infrastructure that needs to occur if in Async mode:-

.. Do we not have to provide a Cancel_Request (From memory, I think the
method is .abort() for the XHR object?) function?

.. If the user chooses to cancel the request does it really only cancel the
client end and leave the server clocking up cpu cycles and i/o for no good
reason, and the user is now free to kick off another dodgy query>

.. If the user has hit the "Confirm transaction" button do we not have to
make sure to disable that button while the async XHR request is in progress
otherwise the user's bank statement could end up with transferred $1000 no
$2000 nope $3000 Doh!

.. Is it not like CPM and if what the XHR (or other more sensible server
request API) has to provide is on the critical path then there's no point
letting the user continue 'cos the only other valid thing left to do is
click over the clock?

.. In most (a lot? at least some?) cases, is "freeing up the event thread for
the Cancel Button" the only valid reason to go Async? (And if you're not
providing a cancel button then surely the options are limited?)

.. I've seen at least one predictive text thingy that is still providing
Select Lists for the first character entered of a surname while the user has
finished typing :-( And then key 2, key 3. . . (But admittedly I'm certainly
not arguing that the user should wait 2secs between keystrokes while a
synchronous request gets the matching list :)

I suppose my question is, "What is this multi-tasking that you'd have the
user do while they're waiting for a response?"

Cheers Richard Maher

PS. Not being able to close the window (without the "Program is not
responding" crap) is certainly a bummer.
 
I

Ian Collins

Richard said:
PS. Not being able to close the window (without the "Program is not
responding" crap) is certainly a bummer.
Which is no different from a "regular" desktop application that's
waiting for a repose to come back from something that has become mute.
 
R

Richard Maher

Hi Ian,

Ian said:
Which is no different from a "regular" desktop application that's
waiting for a repose to come back from something that has become mute.

I didn't know this was a global desktop issue; so I guess no disadvantage
there then either.

But to be fair to -Lost, surely one big disadvantage of serialized
synchronous requests occurs if/when the opportunity for multiple parallel
requests arises (Struggling for an example this early, but let's say
"Roll-up sales figures from the five regional offices") Given that there are
no/few concurrency and locking issues due to the seperate remote databases,
a near linear improvement in performance can be achieved by using Asynch XHR
and kicking all the request off at once, and then sitting at a barrier until
they all come back.

I personally use Sockets with blocking Sends with a variation on subsequent
Blocking Recvs: - I supply a SetSoTimeout(msecs) method so that a lengthy
query may return several zero-byte (my flag to indicate timeout) receives
and then give the event thread enough time to process things, like "cancel"
or "Working. . ." message, before rescheduling (setTimer("readSocket()",0))
another read. Once the result-set has started coming back then I
setSoTimeout(backToNormalXmsecs). [But then XHR won't talk to you until the
entire/complete/unmanagably-large result set has been materialized; so why
would anyone using XHR care about parallelism?]

Anyway, what I'd *really* like to know is "How does XMLHttpRequest work?"
How does it provide this Asynchronous Callback or Up-Call, back to the
browser's page? Is (or can) this mechanism be made generic? If I have a
thread running in a Java Applet, can I manufacture a browser-recognizable
event object and instantiate a browser-side fireEvent() method? What is the
API for this?

Does anyone know the inner workings of XMLHttpRequest, and if so can they
please share that information with us/me?

Cheers Richard Maher
 
H

HugeBob

Hi All,

Problem solved!! With the aid of Firebug (God bless the makers of
Firebug!!!), I was
able to determine that the global variable set by the
onreadystatechange handler wasn't being set at all. I think there
must be a scope issue with that global variable. At least in Firefox
and Netscape anyway. Firebug showed me that responseText was clearly
populated with the data I expected. Firefox seems to have been
differentiating between the global g_groupListXML and the local one in
the handler.

var g_groupListXML = null;
function ajaxGetGroupUserListXML(url)
{
var xmlHttp = null;
xmlHttp = getXMLHTTPRequestObject( );
xmlHttp.onreadystatechange = function ()
{
if (xmlHttp.readyState ==
4)
{
g_groupListXML =
xmlHttp.responseText;
}
};
xmlHttp.open("GET", url, false);
xmlHttp.send(null);
}
 

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

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top