【问题标题】:Get zone-free window methods with Zone.js使用 Zone.js 获取无区域窗口方法
【发布时间】:2016-11-11 00:25:45
【问题描述】:

可以通过加载的 Zone.js 以某种方式访问​​无区域的 window 方法(setTimeout 等)吗? Zone.js 会暴露原始未打补丁的方法吗?

可能的用例示例是 Angular 2 应用程序,它在 Angular 2 材料数据绑定方面存在一些问题,需要调用 un-zoned setTimeout 作为临时但即时的解决方法 - 在问题得到正确修复之前。

【问题讨论】:

    标签: javascript typescript angular zonejs


    【解决方案1】:

    是的,基本上原生方法可以通过

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

    或 目标['zone_symbol'方法名]

    window['__zone_symbol__setTimeout']
    

    你可以通过

    访问 NativePromise
    window['__zone_symbol__Promise']
    

    稍后我会列一个清单。

    【讨论】:

    • 好一个Zone['__symbol__'](methodName)
    【解决方案2】:

    我认为您需要为此利用 NgZone 及其 runOutsideAngular 方法。这是一个示例:

    constructor(private ngZone:NgZone) {
    }
    
    setTimeout(() => {
      this.ngZone.runOutsideAngular(() => {
        // do something
      });
    }, 1000);
    

    【讨论】:

    • 谢谢,太好了,这涵盖了给定的情况。关于如何完全避免/卸载 Zone.js 的任何见解? This question 说明 Zone 可能会为非 Angular 应用程序引入全局副作用。虽然捕捉拒绝是一个好习惯,但 ES6 承诺不应该抱怨未处理的拒绝,而且似乎没有办法关闭 Zone.js,就像 Bluebird 可以使用 Promise.onUnhandledRejection(noop) 一样。
    • 不客气!我认为您不能使用 Angular2,因为 Zone.js 会触发更改检测。没有区域,模板中不会更新任何内容;-) 我看到你回答了这个问题 ;-)
    • 这里的setTimeout 看起来仍然会触发额外的不需要的ChangeDetection 循环
    【解决方案3】:

    除了答案之外,从 Zone.js 0.6.12 开始,可以使用 __zone_symbol__ 前缀访问原始方法(可能会发生变化)。

    window.__zone_symbol__setTimeout

    【讨论】:

      【解决方案4】:

      我喜欢这样:

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

      然后在不需要 ChangeDetection 的地方使用它们:

      setTimeoutNoZone(() => { ... }, 1000)
      

      【讨论】:

        【解决方案5】:

        你还应该注意 Promise::then

        我在我的项目中实现了以下 util 函数

        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));
        }
        

        【讨论】:

        • 我不确定上面的代码有什么意义。 new __zone_symbol__Promise(...).then 方法是否真的使用区域并且应该被覆盖?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-05-14
        • 1970-01-01
        • 2011-08-21
        • 2018-07-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多