jQuery AJAX Error Handling with HTTP Status Code

I’m working with an API that uses proper HTTP status codes for errors and responds with JSON-encoded messages and the correct Content-Type headers. My challenge is that when I use jQuery’s $.ajax(), the error callback triggers on any HTTP error status, bypassing the success callback even if the response contains useful JSON data.

This setup forces me to handle errors in two places: in the success callback for non-critical errors and in the error callback for HTTP-related issues. This approach doesn’t feel very DRY, as I’m duplicating error handling logic in each AJAX call. I’m wondering if there’s a more efficient paradigm to avoid repeating the same error handling twice while still effectively capturing both types of responses.

Here My Code With Error:

$.ajax({
    // ...
    success: function(response) {
        if (response.success) {
            console.log('Success!');
            console.log(response.data);
        } else {
            console.log('Failure!');
            console.log(response.error);
        }
    },
    error: function(xhr, status, text) {
        var response = $.parseJSON(xhr.responseText);

        console.log('Failure!');

        if (response) {
            console.log(response.error);
        } else {
            // This would mean an invalid response from the server - maybe the site went down or whatever...
        }
    }
});

To address the issue of handling HTTP errors and JSON responses in a DRY way, we can consolidate the error handling into one location, while still capturing the success or failure of the response meaningfully. One effective way is to check the HTTP status code in the success callback and use a unified error-handling function for both cases.

Correct Code:

codefunction handleError(response) {
console.log('Failure!');
if (response && response.error) {
console.log(response.error);
} else {
console.log("Invalid response from the server.");
}
}

$.ajax({
url: 'your-api-url',
method: 'GET',
dataType: 'json',
success: function(response, status, xhr) {
if (xhr.status >= 200 && xhr.status < 300 && response.success) {
console.log('Success!');
console.log(response.data);
} else {
handleError(response);
}
},
error: function(xhr, status, text) {
var response;
try {
response = JSON.parse(xhr.responseText);
} catch (e) {
response = null;
}
handleError(response);
}
});

Explanation:

  1. handleError Function: This function consolidates the error handling to avoid redundancy. It checks if the response contains an error field and logs it; otherwise, it logs a generic error message.
  2. success Callback:
    • Checks if the HTTP status code is successful (in the range of 200 to 299) and if the response itself is successful (response.success).
    • If both conditions are met, it logs success data; otherwise, it calls handleError to handle the error within the success callback.
  3. error Callback:
    • Attempts to parse the JSON response using JSON.parse.
    • If parsing fails, response is set to null to indicate an invalid response from the server.
    • Calls handleError to handle errors uniformly.

Final Thought:

In summary, consolidating error handling in AJAX requests helps create cleaner, more maintainable code. By using a single error-handling function and ensuring we check HTTP status codes directly within the success callback, we simplify the logic and avoid redundant checks. This approach not only makes the code more DRY but also ensures that we handle different types of errors gracefully. Adopting this structure can improve readability and help developers quickly pinpoint issues, leading to more reliable and efficient AJAX calls in jQuery.

Related blog posts