views:

201

answers:

3

I have the following piece of code:

// setup the AJAX request
var pageRequest = false;
if(window.XMLHttpRequest)     pageRequest = new XMLHttpRequest();
else if(window.ActiveXObject) pageRequest = new ActiveXObject("Microsoft.XMLHTTP");

// callback
pageRequest.onreadystatechange = function() {

    alert('pageRequest.readyState: ' + pageRequest.readyState
        + '\npageRequest.status: ' + pageRequest.status);
}

pageRequest.open('POST','ajax.php',true);

// q_str contains something like 'data=value...'

pageRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
pageRequest.setRequestHeader("Content-length", q_str.length);
pageRequest.setRequestHeader("Connection", "close");

pageRequest.send(q_str);

This works fine in Chrome, but IE chokes on it, spitting out an "Unspecified error." and it points to the line with the alert() in it. Why can't it display the alert?

Edit: Okay, after I dismiss the error dialog, I get the three alerts as expected....

Edit: Now it's really getting weird. If I change

alert('pageRequest.readyState: ' + pageRequest.readyState
        + '\npageRequest.status: ' + pageRequest.status);

to

alert('pageRequest.readyState: ' + pageRequest.readyState);

then it works and I get 5 alerts. (1,1,2,3,4)

+1  A: 

Status is the HTTP response the first two times the method is called you get back 1 and 1 as the readyState. readyState 1 means "The object has been created, but the send method has not been called.". At that time there is no status response from the server as it has not received any requests therefore using status in your alert gave you an error.

Adam
Thank you for finally explaining why this alert generates errors. I wonder why it works in Chrome and FF...
George Edison
[Off-topic] Was slightly disappointed to see the Paper Clippy avatar without having the answer begin with "It looks like you are trying to..." :(
akamike
Oh boy! Gotta love the stupidly-annoying paperclip from an 'unnamed piece of office software.'
George Edison
Deep down everybody loves Clippy. (OK, very deep down)
Adam
+1  A: 

Chrome 4 raises an error too (INVALID_STATE_ERR: DOM Exception 11). You'll see the error if you open the Chrome Javascript Console.

Firefox 3.6 also raises an error, but seems to silently discard it (it's not visible in the Error Console). If you wrap the function in a try..catch block you will see the error message (Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE)):

pageRequest.onreadystatechange = function() {
  try {
    alert('pageRequest.readyState: ' + pageRequest.readyState
          + '\npageRequest.status: ' + pageRequest.status);
  }
  catch (e) { 
    alert(e); 
  }
}

The first two times onreadystatechange is invoked in Internet Explorer, readyState is 1 (OPENED). In this state, the request is being sent, but the response has not yet been received. The error is raised when calling the status property in this readyState because there is no HTTP response to read the status from.

This behaviour is compatible with old versions of the W3C XMLHttpRequest specification, which state:

If the status attribute is not available it MUST raise an exception. It MUST be available when readyState is 3 (Receiving) or 4 (Loaded). When available, it MUST represent the HTTP status code (typically 200 for a successful connection).

Exceptions on retrieval

DOMException INVALID_STATE_ERR SHOULD be raised if this attribute is accessed when readyState has an inappropriate value.

Newer versions of the specification, however, state that status must always return a value:

The status attribute must return the result of running these steps:

  1. If the state is UNSENT or OPENED return 0 and terminate these steps.
  2. If the error flag is true return 0 and terminate these steps.
  3. Return the HTTP status code.
Phil Ross
Okay. Ya, I kind of forgot about the error console in Chrome. It also pops up errors for modifying the headers too, so I just ignored the console. My bad.
George Edison
A: 

I think you have a string concatenation problem, when evaluating PageRequest.status (which is an integer). Just try this:

status = pageRequest.status;
status += '';
alert('pageRequest.readyState: ' + pageRequest.readyState \
+ '\npageRequest.status: ' + status);
Sergi
If not, do the same with readyState
Sergi
This isn't related to string concatenation. The result of `string + integer` is to convert `integer` to a string and then concatenate it. Also, Javascript doesn't require escaping for continuation lines. The backslash at the end of your third line just results in a syntax error (invalid character).
Phil Ross