Async callback function in jquery .done not executing
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
When jQuery's .done() callback does not execute, the cause is almost always one of these: the AJAX request failed (so .fail() fires instead), the Deferred object was never resolved, the function using .done() does not return a jqXHR/Deferred object, or $.ajax was replaced by fetch which returns a native Promise (not a jQuery Deferred). Understanding the jQuery Deferred/Promise lifecycle — pending, resolved, or rejected — is the key to debugging .done() issues.
How .done() Works
Cause 1: Request is Failing
The most common reason .done() does not fire is that the request returns a non-2xx status code.
Always add .fail() when debugging to see if the request is erroring.
Cause 2: JSON Parse Error
If the server returns invalid JSON but dataType: 'json' is set, jQuery fails to parse it and triggers .fail() instead of .done().
Cause 3: Function Does Not Return the jqXHR Object
Cause 4: CORS or Network Error
Cross-origin requests fail silently if CORS headers are not set on the server.
Check the browser console for CORS errors like "Access-Control-Allow-Origin" header missing.
Cause 5: Using success Callback Instead of .done()
Migrating to Promises (Modern Approach)
Common Pitfalls
- Not adding
.fail()during debugging: Without.fail(), a failed request gives no indication of what went wrong. Always chain.fail()(or.always()) when debugging.done()issues to see HTTP status codes and error messages. dataTypemismatch causing parse errors: SettingdataType: 'json'when the server returns HTML or plain text causes a parse error, triggering.fail()instead of.done(). Match thedataTypeto the actual Content-Type returned by the server, or omit it to let jQuery auto-detect.- Not returning the jqXHR from a wrapper function: If your function calls
$.ajax()but does notreturnit, the caller getsundefinedand cannot chain.done(). Alwaysreturn $.ajax(...)from wrapper functions. - CORS blocking the request silently: Cross-origin requests blocked by CORS policy show
status: 0in the.fail()callback. Check the browser's Network tab and console for CORS-related error messages. - Mixing jQuery Deferred with native Promises:
fetch()returns a nativePromise, not a jQuery Deferred. Native Promises use.then()and.catch(), not.done()and.fail(). If you migrate from$.ajaxtofetch, update the callback pattern accordingly.
Summary
.done()only fires on successful (2xx) responses — add.fail()to see errors- JSON parse errors (
dataType: 'json'with non-JSON response) trigger.fail(), not.done() - Always
return $.ajax(...)from functions so callers can chain.done() - Check for CORS errors in the browser console when
.fail()showsstatus: 0 - Modern code should use
fetchwithasync/awaitandtry/catchinstead of jQuery AJAX

