6

Can zone-free window methods (setTimeout, etc) be accessed somehow with loaded Zone.js ? Does Zone.js expose the original unpatched methods?

The example of possible use case is Angular 2 app that has some problems with Angular 2 Material data binding and needs to call un-zoned setTimeout as temporary but instant workaround - before the issue will be fixed properly.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565

5 Answers5

7

yes, basically the native method can be access by

target[Zone['__symbol__'](methodName)]

or target['zone_symbol'methodName]

such as

window['__zone_symbol__setTimeout']

and you can access NativePromise by

window['__zone_symbol__Promise']

I will make a list later.

jiali passion
  • 1,691
  • 1
  • 14
  • 19
4

I think that you need to leverage NgZone and its runOutsideAngular method for this. Here is a sample:

constructor(private ngZone:NgZone) {
}

setTimeout(() => {
  this.ngZone.runOutsideAngular(() => {
    // do something
  });
}, 1000);
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • Thanks, excellent, this covers the given case. Any insights on how Zone.js can be avoided/unloaded at all? [This question](http://stackoverflow.com/questions/38265963/unhandled-promise-rejection-when-rejecting-promise-in-angular-2) illustrates that Zone may introduce global side effects for non-Angular applications. While catching the rejections is a good habit, ES6 promise isn't supposed to complain on unhandled ones, and it seems that there's no way to shut Zone.js up, like it could be done with `Promise.onUnhandledRejection(noop)` for Bluebird. – Estus Flask Jul 08 '16 at 13:36
  • You're welcome! I think that you can't with Angular2 since Zone.js triggers change detection. Without zones, nothing will be updated in templates ;-) I saw you answer on the question ;-) – Thierry Templier Jul 08 '16 at 13:39
  • It looks like `setTimeout` here will still trigger additional unwanted ChangeDetection cycle – Kirill Groshkov Nov 20 '20 at 19:45
2

Adding to the answer, the original methods can be reached with __zone_symbol__ prefix, as of Zone.js 0.6.12 (may be a subject to change).

I.e. window.__zone_symbol__setTimeout, etc.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
1

I do like this:

const w: any = window
export const setTimeoutNoZone: typeof setTimeout = w.__zone_symbol__setTimeout
export const setIntervalNoZone: typeof setInterval = w.__zone_symbol__setInterval

And then use them in places where ChangeDetection is not needed:

setTimeoutNoZone(() => { ... }, 1000)
Kirill Groshkov
  • 1,535
  • 1
  • 22
  • 23
0

You should also take care for Promise::then

I've implemented the following util functions in my project

function jb_new_NativePromise(cb) {
  if (window && window.__zone_symbol__Promise) {
    var res = new __zone_symbol__Promise(cb);
    res.then = res.__zone_symbol__then;
    return res;
  }

  return new Promise(cb);
}

function jb_NativePromise_resolve(obj) {
  return jb_new_NativePromise(resolve=>resolve(obj))
}

function jb_native_delay(ms) {
  var set_timeout = window && window.__zone_symbol__setTimeout || setTimeout;
  return jb_new_NativePromise(resolve => set_timeout(resolve, ms));
}
Shai Ben-Yehuda
  • 134
  • 1
  • 2
  • 8
  • I'm not sure what's the point of the code above. Does `new __zone_symbol__Promise(...).then` method really use zones and should be overridden? – Estus Flask Jan 31 '17 at 11:56