angular / zone.js

Implements Zones for JavaScript
https://github.com/angular/angular/tree/master/packages/zone.js/
MIT License
3.25k stars 408 forks source link

feat(core): add runOutsideOfZone ability #1138

Open JiaLiPassion opened 6 years ago

JiaLiPassion commented 6 years ago

This is a new way to improve root zone performance and reduce monkey-patch impact inspired by @mhevery.

  1. If Zone.current is rootZone(Zone.root), we will use native delegate (with a very small wrap) instead of monkey patched version.

For example: After loading zone.js, we call some async operations. For example, in web page, we have Angular Elements and Jquery, the following code will be the jquery part.

import `zone.js/dist/zone.js`; // loaded by `Angular Elements`.
setTimeout(() => { // this will use `native window.setTimeout`
   // the callback will totally outside of Zone.
});
  1. We can use Zone.root.run in other zone to use the native delegate version.
testZone.run(() => {
  Zone.root.run(() => { 
      setTimeout(() => { // will use native delegate
         // will outside zone
     });
  });
});

Now the monkey-patch method will look like this. For example, for setTimeout.

const nativeSetTimeout = window.setTimeout;
window.setTimeout = function() {
  if (Zone.current === Zone.root) {
    return nativeSetTimeout.apply(this, arguments); // this is the native one.
  }
  return patchedSetTimeout.apply(this, arguments); // this is the patched version.
}

@mhevery, @robwormald, please review, thank you!

mleibman commented 6 years ago

How big is the performance improvement impact here? If it is not substantial, I would vote against this change. Alternatively, could this be configurable?

The reason I ask is that this change would break a lot of our code without a way to fix it other than maintaining a local modified version of Zone.js.

We (GCP Console, i.e. https://console.cloud.google.com) use Zone.js for latency instrumentation and rely on monkey-patching Zone.prototype.[runTask|scheduleTask|cancelTask] to track all executed tasks regardless of which zone they run in. If I understand this change correctly, this PR would prevent us from being able to track tasks executed in the root zone.