DEV Community

Kalyan P C
Kalyan P C

Posted on

Zone.js based change detection in angular

Angular’s change detection used to rely on Zone.js, a library that tracks and intercepts asynchronous operations such as events, HTTP requests, and timers. It creates execution contexts (called "zones") around blocks of code. Its key superpower: it monkey-patches (dynamically overrides at runtime) many of the browser's native asynchronous APIs.

Commonly patched APIs include:

  • setTimeout / setInterval / clearTimeout
  • Promise.then / Promise.catch / async/await (via promise rewriting)
  • DOM event listeners (addEventListener for click, input, etc.)
  • XMLHttpRequest / fetch
  • Many others (e.g., requestAnimationFrame, WebSocket callbacks, etc.)

When you call these patched APIs inside an Angular app, Zone.js wraps them so it can:

  • Know when the async task starts
  • Know when it finishes (or errors)
  • Track pending microtasks/macrotasks

How Zone.js + NgZone Worked Step by Step

  • Bootstrap & Zone Creation
    When your Angular app starts (platformBrowser().bootstrapModule(AppModule)), Angular loads Zone.js and creates a special child zone called NgZone (via NgZone service). Your entire app code runs inside this NgZone.

  • Monkey-Patching Happens
    Zone.js overrides browser APIs globally (or within the zone).
    Example: When you write setTimeout(() => { this.count++ }, 1000), Zone.js actually runs something like

// Simplified pseudo-code of what Zone.js does
const originalSetTimeout = window.setTimeout;
window.setTimeout = function(callback, delay) {
  // Zone tracks this task
  const task = Zone.current.scheduleMacroTask('setTimeout', callback, ...);
  return originalSetTimeout(task.callbackWrapper, delay);
};
Enter fullscreen mode Exit fullscreen mode
  • Async Operation Occurs

    • User clicks a button → patched addEventListener fires → handler runs inside NgZone
    • HTTP request completes → patched XMLHttpRequest callback runs
    • Timer fires → patched setTimeout callback runs
  • Zone Notifies Angular

    • Zone.js emits events at key moments, especially when the microtask queue becomes empty (onMicrotaskEmpty) after async work.
    • In ApplicationRef → subscribes to NgZone.onMicrotaskEmpty → Calls tick() → runs full change detection cycle.
  • Change Detection Runs
    Angular traverses the component tree (from root down):

    • Performs dirty checking: compare current vs previous bound values
    • Update DOM only where differences exist
    • In dev mode: runs twice (to catch inconsistencies / side-effects)
    • With ChangeDetectionStrategy.OnPush, it skips subtrees unless inputs change or events fire

This loop repeats after almost any async boundary — making the UI update "magically" after clicks, HTTP responses, timers, etc.

References:

Top comments (0)