如何防止Firebase在Angular 2中重复触发更改检测?

时间:2017-01-04 03:59:22

标签: angular firebase firebase-realtime-database angular2-changedetection zonejs

Firebase使用大量内部异步调用来触发更改检测,因为Angular / Zone猴子修补websockets和setInterval等。即使我没有与我的应用程序进行交互,我看到一个级联变化检测一直在发生,这有助于减慢事情,特别是在移动设备上。

这种默认行为可能很有用,但是我现在使用Firebase的方式我可以非常严格地控制何时需要更新视图,因此来自Firebase的回调以这样的方式使用,即更改检测将无论如何都要手动发生。

我知道将设置更改检测器策略设置为OnPush会对此有所帮助,我正在努力,但我想从各个角度对此进行攻击。

我熟悉区域runOutsideAngular但不确定现在是否在此处应用它,因为所有异步调用都发生在Firebase模块内。

如何让Firebase在角度区域之外完成所有业务?

编辑:显示问题的示例代码:

import {Component} from '@angular/core';

@Component({
  selector: 'test-component',
  template: 'hello world'
})
export class TestComponent {
  ref: Firebase;

  constructor() {
    this.ref = new Firebase('<firebase URL>');
  }

  ngDoCheck() {
    console.log('Check the stack - this is being called continually via async functions used internally by Firebase.');
    debugger;
  }
}

1 个答案:

答案 0 :(得分:3)

回想起来这是显而易见的,但只是在区域外实例化Firebase引用就可以了。 E.g:

import {Injectable, NgZone} from '@angular/core';

// ...

@Injectable()
export class DataService {
  ref: Firebase;

  // ...

  constructor(
    private zone: NgZone
    // ...
  ) {
    // Instantiate Firebase ref outside the zone to prevent its continual internal operations from triggering change detection
    this.zone.runOutsideAngular(() => {
      this.ref = new Firebase('<firebase URL>');
    });

    this.ref.on('value', snapshot => {
      // Change detection will NOT automatically be triggered after this callback
    });
  }
}

通过在我的组件中放置ngDoCheck中的断点,我能够将所有更改检测周期追溯到我实例化Firebase引用的那一行,这暗示在区域外运行它会阻止它们。

请注意,如果你走这条路线,你 以确保在必要时触发更改检测。有关示例,请参阅https://stackoverflow.com/a/34829089/458614