Global AJAX Hook Listeners
In this page:
$(document).ajaxStart(function () { /* first request starts */ });
$(document).ajaxStop(function () { /* all requests done */ });
$(document).ajaxError(function () { /* a request failed */ });
1. What Are Global AJAX Events?
jQuery fires global events on the document for every AJAX request a page makes, letting you hook into all of them from one place instead of adding callbacks to each individual call. This is the mechanism behind features like a site-wide loading spinner that reacts to any AJAX activity.
Example: 1. What Are Global AJAX Events?
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
</style>
</head>
<body>
<button id="runBtn">Run</button>
<button id="resetBtn">Reset</button>
<div id="output"></div>
<script>
$(document).ajaxError(function(event, xhr, settings) {
$("#output").append($("<div>").text("Request failed: " + settings.url));
});
$("#runBtn").click(function() {
$("#output").empty();
$("#output").append($("<div>").text("Sending request..."));
$(document).ajaxComplete(function() {
$("#output").text("An AJAX request just completed, somewhere on the page");
});
$.get("data.php");
});
$("#resetBtn").click(function() {
jQuery(document).off();
$("#output").empty();
});
</script>
</body>
</html>
2. ajaxSend and ajaxComplete
ajaxSend fires right before any AJAX request is sent, and ajaxComplete fires after each one finishes, regardless of whether it succeeded or failed. Together they're commonly used to show and hide a loading indicator around every request a page makes.
Example: 2. ajaxSend and ajaxComplete
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
</style>
</head>
<body>
<button id="runBtn">Run</button>
<button id="resetBtn">Reset</button>
<div id="output"></div>
<script>
$(document).ajaxError(function(event, xhr, settings) {
$("#output").append($("<div>").text("Request failed: " + settings.url));
});
$("#runBtn").click(function() {
$("#output").empty();
$("#output").append($("<div>").text("Sending request..."));
$(document).ajaxSend(function() {
$("#output").append($("<div>").text("Request starting"));
});
$(document).ajaxComplete(function() {
$("#output").append($("<div>").text("Request finished"));
});
$.get("data.php");
});
$("#resetBtn").click(function() {
jQuery(document).off();
$("#output").empty();
});
</script>
</body>
</html>
3. ajaxSuccess and ajaxError
ajaxSuccess fires only after a request completes successfully, and ajaxError fires only when a request fails — narrower than ajaxComplete, which fires either way. These are useful for global error logging or showing a shared error banner without wiring it into every individual AJAX call.
Example: 3. ajaxSuccess and ajaxError
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
</style>
</head>
<body>
<button id="runBtn">Run</button>
<button id="resetBtn">Reset</button>
<div id="output"></div>
<script>
$("#runBtn").click(function() {
$("#output").empty();
$("#output").append($("<div>").text("Sending request..."));
$(document).ajaxSuccess(function() {
$("#output").append($("<div>").text("A request succeeded"));
});
$(document).ajaxError(function() {
$("#output").append($("<div>").text("A request failed"));
});
$.get("data.php");
});
$("#resetBtn").click(function() {
jQuery(document).off();
$("#output").empty();
});
</script>
</body>
</html>
4. Global Loading Indicator
Global events are a natural fit for one loading indicator shared by the whole page, since you don't need to remember to show and hide it inside every AJAX call you write. Show it in an ajaxSend handler and hide it in ajaxComplete, and every request on the page is covered automatically.
Example: 4. Global Loading Indicator
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
#spinner { background: steelblue; color: white; padding: 10px; border-radius: 4px; }
</style>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
#demo :where(p, div, span, li, h1, h2, h3, h4, td, th, blockquote, label, section, article, aside) { border:1px solid #4a7fb5; background:#eaf2fb; padding:6px 10px; margin:4px 0; border-radius:4px; }
#demo :where(ul, ol) { border:1px dashed #888; background:#fafafa; padding:8px 8px 8px 32px; margin:6px 0; }
#demo :where(table) { border-collapse:collapse; }
#demo :where(td, th) { border-radius:0; }
#demo :where(input, select, textarea) { margin:4px 0; }
</style>
</head>
<body>
<button id="resetBtn">Reset</button>
<section id="demo">
<div id="spinner" style="display:none">Loading...</div>
<button id="btn">Load Data</button>
<div id="output"></div>
</section>
<script>
var original = $("#demo").html();
function init() {
$(document).ajaxSend(function() { $("#spinner").show(); });
$(document).ajaxComplete(function() {
$("#spinner").hide();
$("#output").text("Request finished, spinner hidden");
});
$("#btn").on("click", function() {
$("#output").text("Request sent...");
$.get("data.php");
});
}
init();
$("#resetBtn").click(function() {
$("#demo").html(original);
$(document).off();
$(window).off();
$("#output").empty();
init();
});
</script>
</body>
</html>
5. Global Event Practice
Global hooks work best for behavior that should apply universally, like logging or a shared spinner — keep anything specific to one particular request inside that request's own callbacks instead. Mixing page-specific logic into global handlers makes it hard to tell which request triggered which behavior.
Example: 5. Global Event Practice
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<style>
button { padding:6px 14px; margin:4px; background:#2c6aa0; color:white; border:none; border-radius:4px; cursor:pointer; }
#resetBtn { background:white; color:#2c6aa0; border:1px solid #2c6aa0; }
#output { margin-top:10px; padding:8px; border:1px solid #ccc; border-radius:4px; background:#f7f7f7; font-family:monospace; min-height:24px; }
</style>
</head>
<body>
<button id="runBtn">Run</button>
<button id="resetBtn">Reset</button>
<div id="output"></div>
<script>
$(document).ajaxError(function(event, xhr, settings) {
$("#output").append($("<div>").text("Request failed: " + settings.url));
});
$("#runBtn").click(function() {
$("#output").empty();
$("#output").append($("<div>").text("Sending request..."));
$(document).ajaxComplete(function() {
$("#output").text("Logged globally, not inside each request's own callback");
});
$.get("data.php");
$.get("data.php");
});
$("#resetBtn").click(function() {
jQuery(document).off();
$("#output").empty();
});
</script>
</body>
</html>
- Attaching
$(document).ajaxComplete(...)expecting it to fire for one request only, when it fires for every AJAX request on the page. - Attaching these global handlers to an ordinary element instead of
document, or settingglobal: falseon the request, so they never fire. - Using
ajaxErrorto show messages without checking which request failed, so every failure shows the same generic text; use the extra arguments (event, jqXHR, settings).
Chapter Quiz — Complete all 4 topics to unlock
0/4 topics done
Complete these topics first: