codejanitor

AJAX, Safari, and Returning an HTTP Error Code

Mar. 30th, 2006

For my AJAX apps I decided to return a 500 error code if there was some sort of problem on the server side (e.g. user doesn’t have permissions, database error, etc.). That way my onFailure code will be called by prototype and the page will reset itself and let the user know what the problem was. In PHP it just requires a header(’HTTP/1.0 500 We Have a Problem Houston’); Even better is that, because the 500 status code is just a header, I can also pass back XML (i.e. with multiple error messages) if I want.

However, I ran into a problem when debugging this in Safari today. Even though I sent back the 500 status code the onSuccess function was being called in Safari. Alerting the request.status and request.getAllResponseHeaders() gave me “undefined.” After a bit of hunting I figured out that it only happend when my PHP script outputted nothing. The solution? Just have PHP print something (a space suffices) before exiting.

Filed under: Jason @ 6:15 pm

AJAX Timeouts with Prototype

Mar. 23rd, 2006

I’ve been implementing some AJAX goodness in Mayday and other FastFrame apps lately. In my reading of the various pitfalls of AJAX one that popped up repeatedly was how to handle gracefully a network outage or the webserver going down. For example, Gmail’s chat handles it nicely. When I turn off my airport connection Gmail chat lets me know that it can’t contact the server and maybe my connection is down. Much better than an endlessly spinning hour glass, or worse, not letting the user know their action was never completed.

Anyhow, after some research I found an excellent post over at the AJAX blog on a general solution to the problem of aborting an AJAX request after a specified amount of time. After a bit of munging I got it to work nicely with prototype, the javascript library of my choice (You may want to check out this Prototype reference if you don’t know how to use it). Here’s the code, commented to explain what’s going on:


function callInProgress (xmlhttp) {
switch (xmlhttp.readyState) {
case 1: case 2: case 3:
return true;
break;
// Case 4 and 0
default:
return false;
break;
}
}
function showFailureMessage() {
alert('uh oh, it looks like the network is down. Try again shortly');
}
// Register global responders that will occur on all AJAX requests
Ajax.Responders.register({
onCreate: function(request) {
request['timeoutId'] = window.setTimeout(
function() {
// If we have hit the timeout and the AJAX request is active, abort it and let the user know
if (callInProgress(request.transport)) {
request.transport.abort();
showFailureMessage();
// Run the onFailure method if we set one up when creating the AJAX object
if (request.options['onFailure']) {
request.options['onFailure'](request.transport, request.json);
}
}
},
5000 // Five seconds
);
},
onComplete: function(request) {
// Clear the timeout, the request completed ok
window.clearTimeout(request['timeoutId']);
}
});

Filed under: Jason @ 3:36 pm