【问题标题】:Angular Firestore subscribe() fires twiceAngular Firestore subscribe() 触发两次
【发布时间】:2021-08-03 11:10:11
【问题描述】:

我只想在我的 Firebase 文档数据更改时调用一次函数,但是将 .subscribe() 链接到我的 valueChanges() 会导致订阅每次有更新时触发两次。

无需订阅的基本代码:

home.component.ts:

constructor(private firestore: AngularFirestore) { }

ngOnInit(): void {
    let docName = this.buildDocName();
    this.plants = this.firestore.collection('officePlants').doc(docName).valueChanges();
}

home.component.html:

<mat-list *ngIf="(plants | async)">
    <mat-list-item>Humidity: {{ (plants | async)?.humidity }}</mat-list-item>
    <mat-list-item>Temperature: {{ (plants | async)?.temperature }}</mat-list-item>
</mat-list>

此代码导致订阅触发两次:

home.component.ts:

ngOnInit(): void {
    let docName = this.buildDocName();
    this.plants = this.firestore.collection('officePlants').doc(docName).valueChanges()
        .subscribe(data => {
            if (!data)
                return;

            console.log('doc updated...', data);
            // ...
        });
}

【问题讨论】:

    标签: angular firebase google-cloud-platform google-cloud-firestore rxjs


    【解决方案1】:

    它实际上可能会更改两次,而您的订阅正在做它应该做的事情。你只是没有处理那个案子。如果没有变化,请尝试对其进行去抖动或过滤。

    this.plants = this.firestore.collection('officePlants').doc(docName).valueChanges()
      .pipe(
        debounceTime(500)
        //distinctUntilChanged() // or try this, ignores equal data
       )
      .subscribe(data => { /*...*/});
    

    第二个问题可能是,您忘记了unsubscribe,并且您同时有两个实时订阅。你需要正确地摆脱它们。

    ngOnDestory() {
      this.plants.unsubscribe();
    }
    

    【讨论】:

      【解决方案2】:

      你的两个订阅导致了这个问题,试试这个来解决这个问题:

      ngOnInit(): void {
        let docName = this.buildDocName();
        this.plants = this.firestore.collection('officePlants').doc(docName).valueChanges().pipe(shareReplay());
        this.plants.subscribe(data => {
              if (!data)
                  return;
      
              console.log('doc updated...', data);
              // ...
          });
      }
      

      看看pitfall 2 for a deeper explanation.

      更新: 抱歉,没有看到多个管道。在模板中尝试一下:

      <mat-list *ngIf="plants | async as pl">
          <mat-list-item>Humidity: {{ pl.humidity }}</mat-list-item>
          <mat-list-item>Temperature: {{ pl.temperature }}</mat-list-item>
      </mat-list>
      

      【讨论】:

      • 我添加了 import { shareReplay } from 'rxjs/operators';但这仍然会导致 2 个回调
      • 感谢您的更新。我试过了,它仍然以某种方式发出 2 个事件
      猜你喜欢
      • 2021-12-20
      • 1970-01-01
      • 2016-10-07
      • 1970-01-01
      • 2018-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多