Advanced AJAX with $.ajax
Use the full $.ajax option set: methods, headers, data types, and real error handling.
The shortcuts $.get, $.post, and $.getJSON are all thin wrappers over one workhorse: $.ajax(). Reach for the full form the moment you need custom headers, a specific method, or serious error handling.
The options that matter
| Option | Purpose |
|---|---|
url, method | where and how (GET, POST, PUT, DELETE) |
data | payload; jQuery serializes objects for you |
dataType | expected response: json, text, html |
headers | custom request headers (auth tokens, etc.) |
timeout | abort after N ms |
Error handling you can trust
$.ajax returns a promise, so prefer .done() / .fail() / .always() over inline callbacks:
$.ajax({
url: "/api/save",
method: "POST",
data: JSON.stringify({ name: "Ada" }),
contentType: "application/json",
dataType: "json",
timeout: 8000
})
.done(function (data) { console.log("saved", data); })
.fail(function (jqXHR, textStatus) {
// textStatus: "timeout", "error", "abort", "parsererror"
console.log("failed:", textStatus, jqXHR.status);
})
.always(function () { console.log("request finished"); });.fail receives the jqXHR object — read jqXHR.status for the HTTP code and textStatus to tell a real 500 apart from a client-side timeout.
Example
When to use it
- A multi-tenant SaaS app uses $.ajaxSetup() to attach a tenant ID header to every AJAX request globally.
- A retry mechanism wraps $.ajax() in a function that re-issues the request on 503 responses up to three times.
- An upload form sends binary data as FormData via $.ajax() with processData: false to bypass jQuery's serialisation.
More examples
Global AJAX setup for auth headers
$.ajaxSetup() sets defaults for all subsequent AJAX calls; here the beforeSend hook injects the token once globally.
<script>
$.ajaxSetup({
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + localStorage.getItem("token"));
}
});
// Every subsequent $.get / $.post automatically includes the header
$(function () {
$.get("/api/me", function (user) {
console.log("Logged in as:", user.name);
});
});
</script>Upload FormData with $.ajax()
processData: false and contentType: false prevent jQuery from touching the FormData, letting the browser set the multipart boundary.
<input type="file" id="file" />
<button id="upload">Upload</button>
<p id="result"></p>
<script>
$(function () {
$("#upload").click(function () {
var fd = new FormData();
fd.append("file", $("#file")[0].files[0]);
$.ajax({
url: "/api/upload",
method: "POST",
data: fd,
processData: false,
contentType: false,
success: function (res) { $("#result").text("Uploaded: " + res.filename); }
});
});
});
</script>Retry request on server error
The fail handler checks the status code and recursively calls retryAjax until retries are exhausted or it succeeds.
<button id="req">Request with retry</button>
<p id="log"></p>
<script>
function retryAjax(opts, retries) {
return $.ajax(opts).fail(function (xhr) {
if (retries > 0 && xhr.status >= 500) {
return retryAjax(opts, retries - 1);
}
$("#log").text("Failed after retries: " + xhr.status);
});
}
$(function () {
$("#req").click(function () {
retryAjax({ url: "/api/data" }, 3)
.done(function (d) { $("#log").text(JSON.stringify(d)); });
});
});
</script>
Discussion