RxJS - подписаться только один раз, но не завершить Observable - PullRequest
0 голосов
/ 09 декабря 2018

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

interface User {
   name: string;
   projectId: string;
   dataThatChangesALotInRealTime: Object;
}

userData: Observable<User>

Эта наблюдаемая userData используется в компоненте для отображения некоторых данных, которые изменяютсяв настоящее время.например,

<p>
{{ (userData | async)?.dataThatChangesALotInRealTime }}
</p>

Теперь я хочу вставить некоторые данные в базу данных в соответствии с текущими данными в userData наблюдаемом.Вот функция

addToDatabase() {
  let sub = this.userData.subscribe(data => {
     this.exampleDatabase.doc(`test/${data.dataThatChangesALotInRealTime.id}`)
          .add({ test: 'hello'})
     sub.unsubscribe() // <- This
  })
}

Вопрос

Это правильное решение для отмены подписки внутри подписки, чтобы избежать многократной вставки в базу данных?Есть ли другой / лучший способ сделать это?

Это просто минималистичный пример: если у вас есть какие-то вопросы или мое объяснение плохое, дайте мне знать в комментариях, и я обновлю свой вопрос.Спасибо

Ответы [ 2 ]

0 голосов
/ 09 декабря 2018

Вы можете использовать takeUntill Operator.Он принимает в качестве аргумента вторую Наблюдаемую информацию, он отслеживает вторую подписку Наблюдаемой и отбрасывает после того, как выдает значение или завершает свою работу.

export class TakeUntilCardComponent implements OnInit, OnDestroy {
  message: string;
  private unsubscribe$ = new Subject();
  constructor(private upperCaseService: UpperCaseService) {}

  ngOnInit() {
    this.upperCaseService.getUpperCaseMessage()
      .takeUntil(this.unsubscribe$)
      .subscribe((message: string) => this.message = message);
  }

  ngOnDestroy(): void {
    this.unsubscribe$.next();
    this.unsubscribe$.complete();
  }
}

здесь полностью функционирует demo

Также есть очень хороший блог об этом, если вы хотите сослаться на него! Не отписывайтесь

0 голосов
/ 09 декабря 2018

Вы можете использовать оператор first:

this.userData.pipe(first()).subscribe(...);

Это автоматически завершится (и, следовательно, откажется от подписки) после того, как будет выдано первое значение.

Обратите внимание, что вы должны убедиться, что он излучает хотя бы один раз перед завершением, иначе будет выдано сообщение об ошибке.Если вы не можете гарантировать это, вы можете использовать take(1) вместо:

this.userData.pipe(take(1)).subscribe(...);

Обратите внимание, что это на самом деле не изменяет наблюдаемую userData напрямую, поэтому другие подписки на нее будут продолжать излучаться независимо.Это связано с тем, что операторы в rxjs не модифицируют наблюдаемые, а вместо этого возвращают новую наблюдаемую.

...