Posts Tagged ‘XMLHttpRequest’

Timeout your XHR requests

Client-side timeouts on XHR requests isn’t something I’ve ever thought a whole lot about. The default is no timeout and in most cases, where you’re kicking off an XHR request in response to a user interaction, you probably won’t ever notice an issue. That said, I ran into a case with ScratchGraph on Chrome where not having a timeout specified, along with some client-side network errors, left the application in a state where it was unable to send any more XHR requests.

ScratchGraph continuously polls its server for new data and every so often I would notice that the XHR calls would stop, with the application left in a broken state, unable to make any AJAX calls. This typically (but not always) occurred when the machine woke up from being put to sleep and in the console there would be a few error messages, typically a number of ERR_NETWORK_IO_SUSPENDED and ERR_INTERNET_DISCONNECTED errors. Testing within my development environment, it was impossible to reproduce. Finally, I came across this StackOverflow post that pointed out that not having a timeout specified on the XHR calls would result in these errors.

I’m still not exactly sure of the interplay between Chrome, the XHR requests, and the network state that results in this situation, but since adding a timeout, I’ve yet to notice this behavior again. It’s also worth noting that it’s very simple to add a timeout on an XHR request:

var xhr = new XMLHttpRequest();
xhr.open(
'GET', '/hello', true);
xhr.timeout = 500;
// time in milliseconds

Safari 5 form submission bug

This applies specifically to Safari 5 (no problems in Safari 4) and forms with an enctype of multipart/form-data, submitted with a POST request built manually (for an AJAX [XMLHttpRequest] call).

Safari 5 injects a “charset=UTF-8” name/value pair into the ContentType field after the boundary string. This generates an invalid request. On the server-side of things, this resulted in no data in PHP’s $_POST global variable.

I tracked down the issues thanks to this post. The bug itself is a WebKit bug, described here.

The simple fix is to prevent Safari from automatically putting the charset parameter in by putting it in manually – before the boundary string. Here’s some jQuery code that demonstrates the issue/fix:

function ajaxSubmitForm(servlet, theForm, extraFunc)
{
var boundaryString = 'AaB03x';
var boundary = '--' + boundaryString;

var requestBody = new Array();

requestBody.push(boundary);

for (var i=0; i<theForm.length; i++)
{
requestBody.push('Content-Disposition: form-data; name="' + theForm.elements[i].name + '"');
requestBody.push('');
requestBody.push(theForm.elements[i].value);
requestBody.push(boundary);
}

var reqBodyText = requestBody.join('\r\n');

$.ajax({
url: servlet,
type: 'POST',
contentType: 'multipart/form-data; charset=UTF-8; boundary=' + boundaryString + '',
data: reqBodyText,
error: function(reqobj, errType, exceptionObj){
alert('Failed to submit form data.\r\nStatus = ' + reqobj.statusText);
},

success: function(xml)
{
if(extraFunc != null)
extraFunc();
}

});
}

XML DOM object to string conversion

One of those simple things which has eluded me for far too long. I finally found the solution here:

var string = (new XMLSerializer()).serializeToString(xmlobject); alert(string);

While the above is good to know, I’ve also discovered I don’t need it. I was looking to convert an XML DOM object, from an AJAX call, to plain text, but the XMLHttpRequest.responseText property provides just that. For jQuery users like myself, the XMLHttpRequest can be access via a synchronous jQuery.ajax call as the return value, or asynchronously via. the jQuery.ajax.complete callback or the jQuery.ajax.success callback (as of jQuery 1.4 the XMLHttpRequest object is now the third parameter).