← Back to jQuery Course | Chapter 10: Advanced AJAX | Lesson 3 of 4

Global AJAX Hook Listeners

Global AJAX events let you run code for many AJAX requests at once. They are useful for shared loading messages and logging.
Syntax
javascript
$(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?

javascript
<!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

javascript
<!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

javascript
<!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

javascript
<!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

javascript
<!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>
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Attaching $(document).ajaxComplete(...) expecting it to fire for one request only, when it fires for every AJAX request on the page.
  2. Attaching these global handlers to an ordinary element instead of document, or setting global: false on the request, so they never fire.
  3. Using ajaxError to 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:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.