Atmosphere/atmosphere — Issue #126: jquery.atmosphere.js invokes callback for non-finished responses
Author: hpihkala
Created: 2011-12-16 15:11:48+00:00
State: open

When long polling, the script invokes the callback function even if the underlying XMLHttpRequest is not complete! The XMLHttpRequest has a readyState-field, where value 4 means "complete" and 3 means "in progress". This COULD be intended behavior, but then there should be a possibility to check the state from within the callback. Here is the relevant code from jquery.atmosphere.js:

```javascript
if (ajaxRequest.readyState == 4) {
jQuery.atmosphere.request = request;
if (request.suspend && ajaxRequest.status == 200) {
jQuery.atmosphere.executeRequest();
}
if (jQuery.browser.msie) {
update = true;
}
} else if (!jQuery.browser.msie && ajaxRequest.readyState == 3 && ajaxRequest.status == 200) { // ERROR?
update = true;
} else {
clearTimeout(request.id);
}
if (update) {

// ......

if (response.responseBody.indexOf("parent.callback") != -1) {
var index = 0;
var responseBody = response.responseBody;
while (responseBody.indexOf("('", index) != -1) {
var start = responseBody.indexOf("('", index) + 2;
var end = responseBody.indexOf("')", index);
response.responseBody = responseBody.substring(start, end);
index = end + 2;
jQuery.atmosphere.invokeCallback(response);
}
} else {
jQuery.atmosphere.invokeCallback(response);
}
}
```

The line I commented "ERROR?" is the one where "update" is set to true even though readyState is 3. Due to lacking comments I don't really understand why.

To reproduce this you need to push large responses that the server splits into several HTTP chunks, for example on my Jetty 6.x the limit seems to be by default 32k.

From the callback function there is no way to check what the readyState is, because the original XMLHttpRequest object is not passed to it. Again, I'm not sure what the intended behavior is, but possible fixes include:

1) To prevent invoking the callback if readyState != 4, OR
2) To include the readyState in the object that gets passed to the callback

Solution 1 could have side effects, readyState 3 might be used with some transports. At least when long-polling the app should not be able to see incomplete responses.

Solution 2 makes the app responsible for checking the state of the response, which might not be good.

What do you think?