如何使用 angulafire2 正确初始化和分配可观察对象?

How do I properly initialize and assign a observable using angulafire2?

我正在使用 Angular 6 和 Rxjs 6。

以下代码将在 ListFormsComponent 处一遍又一遍地抛出 undefined ,直到 ObservablegetForms() 分配,然后它将显示数据。 getForms() 在尝试导航到 ListFormsComponent 页面时由导航服务调用。

FormService.ts

export class FormService {

  public forms$: Observable <Array<Form>> ;
  public assignedForms$: Observable <Array<Form>> ;
  public form$: Observable <Form>;
  constructor(
    private afs: AngularFirestore,
    private authService: AuthService,
  ) {}

  getForms() {
    let zippedData = zip(this.authService.user$);
    zippedData.subscribe(data => {
      this.forms$ = this.afs.collection('networks')
        .doc(data[0].activeNetworkProfile.id)
        .collection('companyProfiles')
        .doc(data[0].activeCompanyProfile.id)
        .collection<Forms>('inspectionForms')
        .valueChanges();
    })
  }

}

ListFormsComponent.ts

export class ListFormsComponent implements OnInit {
  public forms: Forms[];
  constructor(private formService: FormService, private navigateService: NavigationService) {

    this.formService.forms$.subscribe(forms => { //<---Error here this.formService.forms$ is undefined
      this.forms = forms;
      console.log("Forms inside component");
      console.log(this.forms);
    })
  }
}

ListFormsComponent.html

<mbsc-listview [options]="listSettings" style="display:none">
  <mbsc-listview-item (click)="viewDetails(form.id)" *ngFor="let form of forms">
    <h3 class="mbsc-lv-txt">{{form.name}}</h3>
    <p class="mbsc-lv-txt">{{form.lastEdited | date: 'medium'}} </p>
  </mbsc-listview-item>
</mbsc-listview>

NavigationService.ts

navigateForms() {
  this.formService.getForms();
  this.navigateService.navigate('forms');
}

所以我决定通过在 FormService.ts 的构造函数中执行以下代码(见下文)来初始化可观察对象,它会停止错误,但不会触发 ListFormsComponent.ts 中的订阅.我假设当 valueChanges() returns Observableforms$ 时它会破坏 subscriptions 的其余部分。

this.forms$ = new Observable<Array<Forms>>();

所以问题出在这个函数中:

navigateForms() {
  this.formService.getForms();
  this.navigateService.navigate('forms');
}

您调用了 this.formService.getForms();,它将在 FormService 上初始化 forms$。但与此同时,您还导航到 forms,这将呈现 ListFormsComponent。在您的 ListFormsComponent 中,您正在执行 formService.forms$ ,此时可能尚未初始化。因此你得到它作为 undefined.

而不是使用 forms$,我会简单地从 getForms 方法返回 Observable 值,我会在 ListFormComponent 中调用它ngOnInit方法:

export class FormService {

  public forms$: Observable <Array<Form>> ;
  public assignedForms$: Observable <Array<Form>> ;
  public form$: Observable <Form>;
  constructor(
    private afs: AngularFirestore,
    private authService: AuthService,
  ) {}

  getForms() {
    return zip(this.authService.user$).pipe(
      flatMap(data => {
        return this.afs.collection('networks')
          .doc(data[0].activeNetworkProfile.id)
          .collection('companyProfiles')
          .doc(data[0].activeCompanyProfile.id)
          .collection<Forms>('inspectionForms')
          .valueChanges();
      })
    );
  }

}

然后在 ListFormsComponent 中:

export class ListFormsComponent implements OnInit {
  public forms: Forms[];
  constructor(
    private formService: FormService, 
    private navigateService: NavigationService
  ) { }

  ngOnInit() {
    this.formService.getForms().subscribe(forms => {
      this.forms = forms;
      console.log("Forms inside component");
      console.log(this.forms);
    });
  }

}

此外,我现在不需要从 navigateForms 调用 getForms。所以我可以摆脱它:

navigateForms() {
  this.navigateService.navigate('forms');
}