Zones

    These zones are execution contexts that allow Angular to track the start and completion of asynchronous activities and perform tasks as required (e.g. change detection). Zone.js provides a global zone that can be forked and extended to further encapsulate/isolate asynchronous behaviour, which Angular does so in its NgZone service, by creating a fork and extending it with its own behaviours.

    The NgZone service provides us with a number of Observables and methods for determining the state of Angular's zone and to execute code in different ways inside and outside Angular's zone.

    It is important to know that Zone.js accomplishes these various interceptions by Monkey Patching common methods and elements in the browser, e.g. setTimeout and . These interceptions can cause unexpected behaviour between external libraries and Angular. In some cases, it may be preferential to execute third party methods outside of Angular's zone (see below).

    NgZone exposes a set of Observables that allow us to determine the current status, or stability, of Angular's zone.

    • onMicrotaskEmpty - Notifies when no more microtasks are queued for execution. Angular subscribes to this internally to signal that it should run change detection.
    • onStable – Notifies when the last onMicroTaskEmpty has run, implying that all tasks have completed and change detection has occurred.

    Subscribing to these can help you determine if your code is unexpectedly triggering change detection as a result of operations that do not affect application state.

    To run code outside of Angular's context, NgZone provides a method aptly named runOutsideAngular. Using this method, Angular's zone will not interact with your code and will not receive events when the global zone becomes stable.

    In this you will see in the log what happens with Angular's zone when code is run in and outside of it.

    You will notice that in both cases clicking the button causes the Angular zone to become unstable due to Zone.js patching and watching HTMLElement.prototype.onclick, however the setInterval executing outside of Angular's zone does not affect its stability and does not trigger change detection.

    Generally, exceptions thrown during a chain of asynchronous events will only include the current method in their stack trace.

    With Zone.js tracking all of our asynchronous calls it can provide us a longer, more detailed, stack trace of the events and calls that occurred leading up to our exception.

    Angular will take care of forking and extending its own zone to display more meaningful stack traces.

    With the following code, we start by calling startAsync which triggers a chain of setTimeouts leading up to an uncaught error.

    This is a typical stack trace that you would see in this scenario, without Zone, showing only the function where the unhandled exception occurred.

    Detailed "Long" Stack trace

    In the stack trace below, you can see the order of events that occurred within this asynchronous chain of function calls, '>>' has been added to point out our functions.

    You'll notice this stack trace includes much more information, including Zone's own task management (e.g. ), as well as the time that elapsed between when the function was queued and when it was executed.