Creo que se puede ver esto en el código jQuery en la línea de GitHub 394 y en:
http://github.com/jquery/jquery/blob/master/src/ajax.js
En depende del código readyState recibe principalmente y una variable donde controla el tiempo de espera:
var onreadystatechange = xhr.onreadystatechange = function(isTimeout) {
// The request was aborted
if (!xhr || xhr.readyState === 0 || isTimeout === "abort") {
// Opera doesn't call onreadystatechange before this point
// so we simulate the call
if (!requestDone) {
jQuery.handleComplete(s, xhr, status, data);
}
requestDone = true;
if (xhr) {
xhr.onreadystatechange = jQuery.noop;
}
// The transfer is complete and the data is available, or the request timed out
} else if (!requestDone && xhr && (xhr.readyState === 4 || isTimeout === "timeout")) {
requestDone = true;
xhr.onreadystatechange = jQuery.noop;
status = isTimeout === "timeout" ?
"timeout" :
!jQuery.httpSuccess(xhr) ?
"error" :
s.ifModified && jQuery.httpNotModified(xhr, s.url) ?
"notmodified" :
"success";
var errMsg;
if (status === "success") {
// Watch for, and catch, XML document parse errors
try {
// process the data (runs the xml through httpData regardless of callback)
data = jQuery.httpData(xhr, s.dataType, s);
} catch(parserError) {
status = "parsererror";
errMsg = parserError;
}
}
// Make sure that the request was successful or notmodified
if (status === "success" || status === "notmodified") {
// JSONP handles its own success callback
if (!jsonp) {
jQuery.handleSuccess(s, xhr, status, data);
}
} else {
jQuery.handleError(s, xhr, status, errMsg);
}
// Fire the complete handlers
if (!jsonp) {
jQuery.handleComplete(s, xhr, status, data);
}
if (isTimeout === "timeout") {
xhr.abort();
}
// Stop memory leaks
if (s.async) {
xhr = null;
}
}
};
Aquí hay un ejemplo para crear errores personalizados: http://stackoverflow.com/questions/1637019/how-to-get-the-jquery-ajax-error-response-text – jantimon