Как предотвратить повторное выполнение моей наблюдаемой подписки для каждого переданного значения? - PullRequest
0 голосов
/ 18 марта 2020

У меня есть длинный фрагмент кода с несколькими вложенными подписками и транзакциями и т. Д.

  updateActivity(value, index) {
    return this.currentDay.subscribe(docRef => {
      let dayRef = this.db.collection('days').doc(docRef[0].payload.doc.id);
      let innerRef = dayRef.collection('session').doc(index.toString())
      return this.db.firestore.runTransaction(function(transaction) {
        return transaction.get(innerRef.ref).then(function() {
          console.log("outermost")
          innerRef.valueChanges().subscribe(toRollback => {
            console.log("toRollback: " + toRollback)
            dayRef.valueChanges().subscribe(toUpdate => {
              console.log("toUpdate: " + toUpdate)
              dayRef.update({
                caloriesBurned: toUpdate["caloriesBurned"] - toRollback["caloriesBurned"], 
                sessionTime: toUpdate["sessionTime"] - toRollback["duration"] })
            })
          })
          transaction.set(innerRef.ref, value);
        })
      })
    })
  }

Суть в том, что этот вызов dayRef.update() обновляет коллекцию в Firebase. Как только коллекция обновится, подписка dayRef.valueChanges() поймет, что есть новое значение для выдачи и повторного запуска, которое будет постоянно обновлять dayRef. Это приводит к бесконечному l oop.

. Идеальное поведение состоит в том, что я подписываюсь на эту наблюдаемую, а затем, используя значения, излучаемые из наблюдаемой, обновляю коллекцию Firebase, из которой наблюдаемая получала свои старые значения из , Поскольку подписка все еще активна, вызов dayRef.update() будет выполняться каждый раз, когда я обновляюсь.

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

edit: с switchMap

dayRef.valueChanges().pipe(switchMap(toUpdate => 
              innerRef.valueChanges().pipe(switchMap(toRollback => 
                dayRef.update({
                  caloriesBurned: toUpdate["caloriesBurned"] - toRollback["caloriesBurned"], 
                  sessionTime: toUpdate["sessionTime"] - toRollback["duration"] })
            ))
          ))

1 Ответ

1 голос
/ 18 марта 2020

Написание вложенных подписок действительно очень плохая практика. Вместо этого цепочка операторов rx js. В вашем примере, я думаю, SwitchMap будет хорошо подойдет. Зависит от того, что вы пытаетесь выполнить sh.

См. Документацию: https://www.learnrxjs.io/learn-rxjs/operators/transformation/switchmap

Редактировать:

Кроме того, попробуйте определить большинство ваших наблюдаемых логи c до транзакции. Если вы можете, определите это вне вашей updateActivity() функции.

Например:

        let dayRef$ = this.currentDay.pipe(
            switchMap(docRef => this.db.collection('days').doc(docRef[0].payload.doc.id))
        );
        let innerRef$ = dayRef$.pipe(
            map(dayRef => dayRef.collection('session').doc(index.toString()))
        );

представляет ваши наблюдаемые.

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