【问题标题】:Angular Service BehaviorSubject displays duplicate data using Async PipeAngular Service BehaviorSubject 使用异步管道显示重复数据
【发布时间】:2021-06-08 16:36:14
【问题描述】:

首先,我有一个服务 - ContractorsService - 带有一个函数 getContractors,它使用 AngularFire 方法对 contractors 数据库进行 Firebase Firestore 调用。

我使用管道首先 switchMap 来自快照的结果,以便获取每个承包商记录的 uid,并将 uid 属性附加到 iContractor 模型的其余部分,然后我根据经过身份验证的 userId 筛选要显示的承包商模板。

我用另一个映射到服务函数isContractorRecordComplete 完成管道,该函数接受contractorId 的参数,并返回Observable<number>,并且该数字附加到映射中的承包商对象。

地图通过将最新的 iContractor 对象添加到 BehaviorSubject 来完成。

该 BehaviorSubject 已公开,并在模板中用作带有异步管道的 Iterable

我的行为不一致:

  • 最初加载页面时,我会在 BehaviorSubject 中显示重复的对象以显示在模板中
  • 编辑承包商并返回承包商列表页面后,页面仅显示编辑的一个承包商,没有其他承包商
  • 其他使用 AngularFire Firestore 快照引用 contractors 数据库的页面仅显示已编辑的 Contractor 对象,没有其他 Contractors

查看下面的最新代码:

contractors.service.ts

getContractors(noIndicator: boolean) {       
   this.userId = JSON.parse(localStorage.getItem('ms_user'))?.uid;
   let _contractorsArray: iContractor[] = [];  

   this.afs.collection('contractors').snapshotChanges().pipe(
      switchMap(actions => actions.map(a => {                    
         const data = a.payload.doc.data() as iContractor;
         const id = a.payload.doc.id;                                                                                
         return { id, ...data };
      })),
      filter(contractor => contractor.userId === this.userId),
      map((c: iContractor) => {
         if(noIndicator == false){
            this.isContractorRecordComplete(c.id).subscribe(completionPercent => {
               let contractor: iContractor = {...c, completionPercent};
               _contractorsArray.push(contractor);
               this.contractorCollection.next(_contractorsArray);
            });
         }

         if(noIndicator == true){
            _contractorsArray.push(c);
            this.contractorCollection.next(_contractorsArray);
         }                                
      })
   )
}

isContractorRecordComplete(uid: string): Observable<number> {
   return this.afs.doc<iContractor>(`/contractors/${uid}`).valueChanges().pipe(
      map(_contractor => {    
         if(_contractor){
            let THEcontractor = new Contractor;
            let populatedFieldSum = 0;
                    
            for (const [requiredKey, data] of Object.entries(THEcontractor.fieldsForCompletion)) {
               Object.keys(_contractor).forEach(cKey => {
                  if(cKey == requiredKey){
                     if(_contractor[cKey] !== undefined && _contractor[cKey] !== ''){
                        populatedFieldSum = populatedFieldSum + data.weight;
                     }

                     if(requiredKey == 'logo' && _contractor[cKey].indexOf('placeholder_contractor.jpg') > -1){
                        populatedFieldSum -= 5;
                     }
                  }
               })
            }                

            return populatedFieldSum;
         } else {
            return 0;
         }
      })
   );
}

contractors.component.html

<section class="grid-container">
  <mat-grid-list cols="2" rowHeight="500px" *ngIf="this.contractorService.contractorCollection$ | async">
    <ng-template ngFor let-contractor [ngForOf]="this.contractorService.contractorCollection$ | async">
      <mat-grid-tile
         *ngIf="!contractor.archived"
         [colspan]="1"
         [rowspan]="1"                    
      >            
         <contractor-card [contractorData]="contractor"></contractor-card>
      </mat-grid-tile>
    </ng-template>        
  </mat-grid-list>
</section>

【问题讨论】:

    标签: angular firebase rxjs observable behaviorsubject


    【解决方案1】:

    你有两个异步管道订阅同一个 observable。那是两个单独的订阅,我认为这会导致您的重复。尝试为您的第一个异步管道设置别名并在第二个管道上使用别名。这样你就订阅一次。

    <section class="grid-container">
      <mat-grid-list cols="2" rowHeight="500px" *ngIf="(this.contractorService.contractorCollection$ | async) as contractors">
        <ng-template ngFor let-contractor [ngForOf]="contractors">
          <mat-grid-tile
             *ngIf="!contractor.archived"
             [colspan]="1"
             [rowspan]="1">            
             <contractor-card [contractorData]="contractor"></contractor-card>
          </mat-grid-tile>
        </ng-template>        
      </mat-grid-list>
    </section>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-03-26
      • 2018-09-11
      • 1970-01-01
      • 2021-05-11
      • 1970-01-01
      • 1970-01-01
      • 2020-03-26
      相关资源
      最近更新 更多