Вложенная наблюдаемая проблема подписки, неспособность отписаться - PullRequest
0 голосов
/ 05 июля 2019

Я использую аутентификацию firebase с Firestore (https://github.com/angular/angularfire2) в моем приложении. С моими текущими правилами Firestore, я обязательно отменяю подписку на все наблюдаемые, полученные из Firestore, прежде чем выйти из системы. Однако я получаю «FirebaseError»: Отсутствует или недостаточно разрешений. "Ошибка, которую я проследил до вложенной подписки, на которую я подписан в рамках подписки, как показано в приведенном ниже коде.

Внутри ngOnDestory я отписываюсь от обеих подписок, но все равно получаю предыдущую ошибку.

this.proposalSubscription = this._posts.retrieveProposals(user.uid)
  .subscribe(proposals => {
      this.proposals = proposals;
      this.proposals.forEach(proposal => {
        this.chatSubscription = this._chat.retrieveChat(proposal.id).subscribe(chat => {
          if (chat) {
            this.chats.set(proposal.id, chat)
          }
        });
      })
    });

Я почти уверен, что теперь проблема заключается в этой строке: this.chatSubscription = this._chat.retrieveChat(proposal.id).subscribe(chat => ... Даже несмотря на то, что я отказываюсь от подписки на обоих экземплярах offerSubscription и chatSubscription, я все равно получаю сообщение об ошибке. Любая идея о том, как я могу это сделатьисправить это? Кроме того, у меня нет большого опыта работы с rxjs и операторами. Есть ли оператор, который я мог бы использовать, чтобы избежать этой вложенной подписки?

Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 06 июля 2019

Вы можете настроить свою подписку следующим образом:

this.proposalSubscription = this._posts.retrieveProposals(user.uid)
                                    .pipe(
                                      switchMap(proposals => {

                                        //if you need to save it in class variable you can save it like this
                                        this.proposals = proposals;

                                        const obs$ = proposals.map(p => {
                                          return this._chat.retrieveChat(p.id)
                                                     .pipe(
                                                       map(chat => {
                                                         this.chats.set(p,id, chat);
                                                       })
                                                     )
                                        });

                                        return forkJoin(obs$);
                                      })
                                    )
                                    .subscribe();

Вы можете составить свою цепочку операторов по своему желанию и иметь только одну подписку.

В ngOnDestory отмените подписку следующим образом:

ngOnDestroy() {

 if(this.proposalSubscription) {
   this.proposalSubscription.unsubscribe()
 }
}

Вы можете избежать явного unsubscribe в ngOnDestroy и поддерживать экземпляр Subscription, используя take(1) , если вы ожидаете оценить this._posts.retrieveProposals(user.uid) наблюдаемый только один раз , например так:

this._posts.retrieveProposals(user.uid)
                                    .pipe(
                                      take(1),
                                      switchMap(proposals => {

                                        //if you need to save it in class variable you can save it like this
                                        this.proposals = proposals;

                                        const obs$ = proposals.map(p => {
                                          return this._chat.retrieveChat(p.id)
                                                     .pipe(
                                                       map(chat => {
                                                         this.chats.set(p,id, chat);
                                                       })
                                                     )
                                        });

                                        return forkJoin(obs$);
                                      }),                                          
                                    )
                                    .subscribe();
1 голос
/ 05 июля 2019

Вложенные подписки - не лучший способ справиться с зависимыми наблюдаемыми, вместо этого мы обычно используем switchMap.Лучший способ управлять несколькими подписками в одном и том же компоненте - это использовать takeUntil, поскольку вы можете передать значение в одну тему и отменить все подписки за один раз.Мы можем сопоставить пропасалию с массивом наблюдаемых и использовать объединение последних, чтобы вернуть массив результатов этих наблюдаемых.

finalise = new Subject();

this._posts.retrieveProposals(user.uid)
  .pipe(
    switchMap(proposals => combineLatest(proposals.map(proposal => this._chat.retrieveChat(proposal.id)))),
    takeUntil(finalise)
  ).subscribe(chats => {
    const chat = proposals.find(p => p);
    this.chats.set(proposal.id, chat)
  });

и в ngOnDestroy

this.finalise.next();

Завершит просмотр всех подписокзавершить в takeUntil.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...