Как бороться со свойствами, которые инициализируются асинхронно в Angular? - PullRequest
0 голосов
/ 01 мая 2018

Я пытаюсь получить коллекцию AngularFirestoreCollection из службы в angular. AngularFirestoreCollection инициализируется асинхронно внутри наблюдаемой подписки. Когда я пытаюсь получить коллекцию из компонента, я получаю сообщение об ошибке, потому что оно не определено.

Вот код моего сервиса:

fokosCollection: AngularFirestoreCollection<Foko>;
myFokos: Observable<Foko[]>;

constructor(auth: AuthService, public afs: AngularFirestore) {

  this.myFokos = auth.user$.switchMap(user => {
    if (user) {
      this.fokosCollection = afs.collection<Foko>('users/' + user.uid + '/fokos');
      return this.fokosCollection.valueChanges();
    }
  });

}

Это код моего компонента:

 this.myListService.fokosCollection.doc(codeInput).valueChanges().take(1).subscribe(foko => {
   getData(foko)
 });

Я попытался создать Субъект, который уведомлял компонент при инициализации Коллекции. Это сработало, когда я перешел непосредственно к этому компоненту. Однако, если я перешел к этому компоненту из другого, тема подписки никогда не вызывалась (поскольку подписка не существовала, когда субъект отправлял коллекцию).

Вот что я попробовал:

fokosCollection: AngularFirestoreCollection<Foko>;
fokosCollectionSubject = new Subject<AngularFirestoreCollection<Foko>>();
myFokos: Observable<Foko[]>;

constructor(auth: AuthService, public afs: AngularFirestore) {

  this.myFokos = auth.user$.switchMap(user => {
    if (user) {
      this.fokosCollection = afs.collection<Foko>('users/' + user.uid + '/fokos');
      this.fokosCollectionSubject.next(this.fokosCollection);
      ...

И я изменил код компонента на этот:

this.myListService.fokosCollectionSubject.take(1).switchMap(fokosCollection => {
    return fokosCollection.doc(codeInput).valueChanges().take(1);
  }).subscribe(foko => {
    getData(foko)
  });

Я могу попытаться получить коллекцию, и если она выдаст ошибку, подпишитесь на тему. Тем не менее, я думаю, что это не будет хорошим кодом. Итак, что лучше всего использовать для асинхронных данных в Angular?

1 Ответ

0 голосов
/ 01 мая 2018

В вашем switchMap вы не возвращаете значение, если пользователь ложен. Вы должны что-то вернуть. Использование оператора filter предотвращает этот случай.

Поскольку вы хотите знать, когда инициализируется fokosCollection, я бы посоветовал вам выставить его как наблюдаемый.

fokosCollection: Observable<AngularFirestoreCollection<Foko>>;
myFokos: Observable<Foko[]>;

constructor(auth: AuthService, public afs: AngularFirestore) {
  this.fokosCollection = auth.user$
    .filter(x => x != null)
    .map(user => afs.collection<Foko>('users/' + user.uid + '/fokos'))
    .shareReplay(1);
  this.myFokos = this.fokosCollection.switchMap(x => x.valueChanges());
}

Я добавил shareReplay(1), чтобы поделиться одной базовой подпиской и воспроизвести последнее значение для новых подписчиков. Вы можете хотеть или не хотеть этого в своем сценарии, но я нахожу, что я вообще хочу это при выставлении наблюдаемых, которые могут иметь несколько подписок.

Тогда в вашем компоненте:

this.myListService.fokosCollection.switchMap(x => x.doc(codeInput).valueChanges()).take(1).subscribe(foko => {
   getData(foko)
 });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...