筛选可观察数组以返回一个结果

时间:2019-03-17 14:33:06

标签: angular firebase google-cloud-firestore

我正在Angular 6和angularfire2中做一个Web应用程序。在我的服务中,我有一个Observable数组,我想对其进行过滤以仅返回一个结果。在所有文档中,有一个名为moderatorAssigned的地图,其ID属性为id,此id是Firebase中用户的uid

我有公司,每个公司都有办公室,并且办公室分配了主持人,我想将分配用户的办公室返回到我的组件。

export interface Company {
  name: string;
  emailAddress: string;
  typeOfService: string;
  offices: Office[];
}

export interface CompanyId extends Company {
  id: string;
}

export interface Office {
  id: string;
  name: string;
  address: string;
  moderatorAssigned: {
    firstName: string;
    id: string;
    lastName: string;
  };
}

组件

export class SeeTurnsComponent implements OnInit {

  officeAssigned: Observable<Office>;

  constructor(private companyService: CompanyService,
              private authService: AuthService) {
  }

  ngOnInit() {
    const userId = this.authService.getUserUid();
    this.officeAssigned = this.companyService.getOfficeAssigned(userId);
  }

}

模板

<div *ngIf="officeAssigned | async as office">
    {{office.id}}
  </div>

服务

private companiesCollection: AngularFirestoreCollection<Company>;
companies: Observable<CompanyId[]>;

  constructor(private afs: AngularFirestore) {
    this.companiesCollection = afs.collection<Company>(
      config.collection_companies,
      ref => ref.orderBy('createdAt', 'desc')
    );

    this.companies = this.companiesCollection.snapshotChanges().pipe(
      map(actions => actions.map(a => {
        const data = a.payload.doc.data() as Company;
        const id = a.payload.doc.id;
        return {id, ...data};
      }))
    );
  }

getOfficeAssigned(userId: string): Observable<Office> {
    this.companies.pipe(
      map(companies => companies.filter(company => {
        company.offices.filter(office => {
          console.log('comparing...');
          if (office.moderatorAssigned && office.moderatorAssigned.id === userId) {
            console.log('office found...');
            return office;
          } else {
            console.log('no office assigned...');
            return of(null);
          }
        });
      }))
    );

    return of(null);
  }

没有数据,也许我做错了。

我的目标是在服务中的companies: Observable<CompanyId[]>内搜索并返回已分配用户的办公室,以在模板中显示数据。

1 个答案:

答案 0 :(得分:2)

您的代码中有很多问题:

getOfficeAssigned(userId: string): Observable<Office> {
    this.companies.pipe(
      map(companies => companies.filter(company => {
        company.offices.filter(office => {
          console.log('comparing...');
          if (office.moderatorAssigned && office.moderatorAssigned.id === userId) {
            console.log('office found...');
            return office;
          } else {
            console.log('no office assigned...');
            return of(null);
          }
        });
      }))
    );

    return of(null);
}

首先,您的方法始终返回of(null)。这是没有意义的。您想返回通过转换this.companies获得的Observable。

因此,代码应类似于:

getOfficeAssigned(userId: string): Observable<Office> {
    return this.companies.pipe(
      map(companies => this.findOfficeWithAssignedUserId(companies, userId))
    );
}

然后实现findCompanyWithAssignedUserId方法并进行测试。请注意,它不需要使用任何与Observable相关的类型或方法。它只需要find该数组的元素。看起来应该像

findOfficeWithAssignedUserId(companies: Array<Company>, userId: string): Office {
    const company = companies.find(c => 
      c.offices.some(office =>
        office.moderatorAssigned.id === userId
      )
    );
    return company && company.offices.find(office =>
      office.moderatorAssigned.id === userId
    );
}

使用flatMap,代码会更好,但是flatMap仍处于试验阶段。还有其他方法可以使该循环更有效,但这应该足够快并能为您提供思路。