How to Track Active AJAX Requests with jQuery $.active

Tracking active AJAX requests in web applications is essential for building responsive UI indicators and creating reliable end-to-end automated tests. jQuery provides an internal property, $.active, which maintains an integer count of all currently pending AJAX requests initiated by jQuery methods. This article explains how $.active works, how to read its value programmatically, and how to utilize it effectively in production and testing environments.

Understanding jQuery $.active

The $.active property is an internal counter built directly into the jQuery library. Every time a jQuery AJAX request begins (via $.ajax(), $.get(), $.post(), or $.load()), the counter increments by one. Once a request finishes—whether it succeeds, fails, or aborts—the counter decrements by one.

When the value is 0, there are no active jQuery AJAX requests running in the background. A value greater than 0 indicates that one or more requests are currently in progress.

Checking the Active Request Count

You can inspect the number of pending requests at any time by accessing the property directly:

console.log("Active AJAX requests:", $.active);

if ($.active === 0) {
    console.log("All jQuery AJAX requests have completed.");
} else {
    console.log("There are currently " + $.active + " request(s) in progress.");
}

Polling $.active in Automated Testing

The primary use case for $.active is within test automation frameworks like Selenium WebDriver, Puppeteer, or Playwright. These tools often need to ensure that dynamic content has fully loaded before executing user actions or making assertions.

Example: Waiting for Requests to Complete in JavaScript

function waitForAjaxToComplete(callback, timeout = 5000) {
    const startTime = Date.now();

    const interval = setInterval(() => {
        if (typeof jQuery !== "undefined" && $.active === 0) {
            clearInterval(interval);
            callback(true);
        } else if (Date.now() - startTime > timeout) {
            clearInterval(interval);
            callback(false); // Timed out
        }
    }, 50);
}

// Usage
waitForAjaxToComplete((success) => {
    if (success) {
        console.log("Safe to proceed with DOM assertions.");
    } else {
        console.error("AJAX requests timed out.");
    }
});

Example: Selenium (Java)

In automated browser tests, you can execute JavaScript directly to verify that the network is idle:

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(webDriver -> ((JavascriptExecutor) webDriver)
    .executeScript("return jQuery.active === 0"));

Global AJAX Events as an Alternative

While $.active provides a snapshot of the current request count, jQuery also offers global event listeners that trigger when requests start and finish. These can be used to manage global loading spinners alongside tracking:

$(document).ajaxStart(function() {
    $("#loading-spinner").show();
});

$(document).ajaxStop(function() {
    // When $.active reaches 0, ajaxStop fires automatically
    $("#loading-spinner").hide();
});

Limitations and Considerations

  1. jQuery Scope Only: $.active exclusively tracks requests initiated by jQuery. It does not monitor requests made using the native fetch API, raw XMLHttpRequest, or third-party libraries like Axios.
  2. Undocumented Property: While stable and widely relied upon across major versions of jQuery (1.x through 3.x), $.active is an internal implementation detail rather than an officially documented public API.
  3. Availability: Ensure that jQuery is loaded on the page before querying $.active, or write a defensive check (window.jQuery && jQuery.active === 0) to prevent runtime reference errors.