DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Rediscovering Angular: Modern Advantages and Technical Stack
  • Angular Input/Output Signals: The New Component Communication
  • Azure Deployment Using FileZilla
  • Angular RxJS Unleashed: Supercharge Your App With Reactive Operators

Trending

  • Integrating Model Context Protocol (MCP) With Microsoft Copilot Studio AI Agents
  • The Full-Stack Developer's Blind Spot: Why Data Cleansing Shouldn't Be an Afterthought
  • Metrics at a Glance for Production Clusters
  • Data Quality: A Novel Perspective for 2025
  1. DZone
  2. Coding
  3. Frameworks
  4. Understanding NgZone

Understanding NgZone

Angular 2 does a lot of things differently from Angular 1, and one of its greatest changes is in change detection.

By 
Tiago Roldao user avatar
Tiago Roldao
·
Oct. 07, 16 · Opinion
Likes (9)
Comment
Save
Tweet
Share
56.7K Views

Join the DZone community and get the full member experience.

Join For Free

Angular 2 does a lot of things differently from Angular 1, and one of its greatest changes is in change detection. understanding how it works has been essential, particularly when using Protractor for E2E testing. This explores how to work with zones for testing and performance. A live example of the mentioned code is here.

The biggest change in how Angular 2 handles change detection, as far as a user is concerned, is that it now happens transparently through zone.js.

This is very different from Angular 1, where you have to specifically tell it to synchronize – even though both the built-in services and the template bindings do this internally. What this means is, while $http or $timeout do trigger change detection, if you use a third party script, your Angular 1 app won’t know anything happened until you call $apply().

Angular 2, on the other hand, does this entirely implicitly –  all code run within the app’s Components, Services or Pipes exists inside that app’s zone, and just works.

So, What Is a Zone?

zone.js’s zones are actually a pretty complicated concept to get our head around. Running the risk of over-simplifying, they can be described simply as managed code calling contexts – closed environments that let you monitor, control, and react to all events, from asynchronous tasks to errors thrown.

The reason this works is, inside these zones, zone.js overrides and augments the native methods – Promises, timeouts, and so on, meaning your code doesn’t need to know about zone to be monitored by it. Everytime you call setTimeout, for instance, you unwillingly call an augmented version, which zone uses to keep tabs on things. 

What Angular does is use zone.js to create it’s own zone and listen to it, and what this means for us as angular users is this – all code run inside an angularapp is automatically listened to, with no work on our part.

Most times, this works just fine – all change detection “just works” and Protractor will wait for any asynchronous code you might have. But what if you don’t want it to? There are a few cases where you might want to tell angular not to wait for / listen to some tasks:

  • An interval to loop an animation
  • A long-polling http request / socket to receive regular updates from a backend
  • A header component that listens to changes in the Router and updates accordingly

These are cases where you don’t want angular to wait on asynchronous tasks/ change detection to run every time they run.

Control Where Your Code Runs With NgZone

NgZone gives you back control of your code’s execution. There are two relevant methods in NgZone – run and runOutsideAngular:

  • runOutsideAngular runs a given function outside the angular zone, meaning its code won’t trigger change detection.
  • run runs a given function inside the angular zone. It is meant to be run inside a block created by runOutsideAngular, to jump back in, and tell angular to start listening again.

So, this code will have problems being tested, as the app will be constantly unstable:

this._sub = Observable.timer(1000, 1000)
    .subscribe(i => {
        this.content = "Loaded! " + i;
    });

Using NgZone, we can avoid that problem:

this.ngZone.runOutsideAngular(() => {
    this._sub = Observable.timer(1000, 1000)
    .subscribe(i => this.ngZone.run(() => {
        this.content = "Loaded! " + i;
    }));
});

Simplifying usage

After understanding how NgZone works, we can simplify its usage, so that we don’t need to sprinkle NgZone.runOutsideAngular and NgZone.run all over the place.

We can create a NgSafeZone service to do exactly that, as the most common use case for this is:

  • Subscribe to an Observable outside the angular zone
  • Return to the angular zone when reacting to that Observable.
@Injectable()
export class SafeNgZone{

  constructor(private ngZone: NgZone) {
  }

  safeSubscribe(
    observable: Observable<T>, 
    observerOrNext?: PartialObserver<T> | ((value: T) => void), 
    error?: (error: any) => void, 
    complete?: () => void) {
      return this.ngZone.runOutsideAngular(() => 
        return observable.subscribe(
          this.callbackSubscriber(observerOrNext),
          error,
          complete));
  }

  private callbackSubscriber (obs: PartialObserver<T> | 
    ((value: T) => void)) {
    if (typeof obs === "object") {
      let observer: PartialObserver<T> = {
          next: (value: T) => {
            obs['next'] && 
              this.ngZone.run(() => obs['next'](value));
          },
          error: (err: any) => {
            obs['error'] && 
              this.ngZone.run(() => obs['error'](value));
          },
          complete: () => {
            obs['complete'] && 
              this.ngZone.run(() => obs['complete'](value));
          }
      };

      return observer;
    }
    else if (typeof obs === "function") {
      return (value: T) => {
        this.ngZone.run(() => obs(value));
      }
    }
  }
}

With this the previous code gets simplified quite a bit:

// The following:
this.ngZone.runOutsideAngular(() => {
    this._sub = Observable.timer(1000, 1000)
    .subscribe(i => this.ngZone.run(() => {
        this.content = "Loaded! " + i;
    }));
});

// Becomes:
this._sub = this.safeNgZone.safeSubscribe(
    Observable.timer(1000, 1000),
    i => this.content = "Loaded! " + i);
AngularJS

Published at DZone with permission of Tiago Roldao, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Rediscovering Angular: Modern Advantages and Technical Stack
  • Angular Input/Output Signals: The New Component Communication
  • Azure Deployment Using FileZilla
  • Angular RxJS Unleashed: Supercharge Your App With Reactive Operators

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!