Angular6 rxjs отписка от подписки по таймеру OnDestroy не работает?

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

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

Захожу, тестирую маршрутизацией на 2 компонента туда-сюда 5-6 раз. Обычно это должно убивать подписку каждый раз, когда я перехожу к следующей.

По прошествии 60 секунд выполняется столько вызовов API, сколько раз я переключался между этими двумя. поэтому я создавал подписку по таймеру каждый раз, когда заходил на один из компонентов, но не уничтожал их.

РЕДАКТИРОВАТЬ, добавил мой полный код OnInit и OnDestroy ниже:

ngOnInit() {

    let mainTimer = timer(0, 60000);

    this.dataSourceSubscription = mainTimer.subscribe(t => {
      this.service.getSection3();
      this.dataSourceSubscription = this.section3.subscribe(data => {
        let countAccepted = data => {
          for (let i = 0; i < data.length; i++) {
            if (
              data[i].DeliveryStatus == "Accepted" &&
              data[i].BookingId == "0"
            ) {
              this.multidropAccepted++;
            }
          }
        };

        let countDepartedSite = data => {
          for (let i = 0; i < data.length; i++) {
            if (
              data[i].DeliveryStatus == "Departed Site" &&
              data[i].BookingId == "0"
            ) {
              this.multidropDepartedSite++;
            }
          }
        };


        let countPending = data => {
          for (let i = 0; i < data.length; i++) {
            if (
              data[i].DeliveryStatus == "Pending" &&
              data[i].BookingId == "0"
            ) {
              this.multidropPending++;
            }
          }
        };

        let countOnSite = data => {
          for (let i = 0; i < data.length; i++) {
            if (
              data[i].DeliveryStatus == "On Site" &&
              data[i].BookingId == "0"
            ) {
              this.multidropOnSite++;
            }
          }
        };

        let countTurnedAway = data => {
          for (let i = 0; i < data.length; i++) {
            if (
              data[i].DeliveryStatus == "Turned Away" &&
              data[i].BookingId == "0"
            ) {
              this.multidropTurnedAway++;
            }
          }
        };


        (this.dataSource = new MatTableDataSource(
          data.filter(
            (value, index, array) =>
              !array.filter(
                (v, i) => JSON.stringify(value) == JSON.stringify(v) && i < index
              ).length
          )
        )),
          (this.dataSource.sort = this.sort),
          (this.dataSource.paginator = this.paginator),
          this.multidropAccepted = 0;
          this.multidropDepartedSite = 0;
          this.multidropPending = 0;
          this.multidropOnSite = 0;
          this.multidropTurnedAway = 0;
          countAccepted(data),
          countDepartedSite(data),
          countPending(data),
          countOnSite(data),
          countTurnedAway(data),
          this.totalDeliveries = data.length;
      });

      this.lastUpdated.subscribe(data => {
        console.log(data);
      })
    })


    let pageTimer = timer(10000, 10000);

    this.pageSubscription = pageTimer.subscribe(t => {
      if (
        this.dataSource.paginator._pageIndex ==
        this.dataSource.paginator.getNumberOfPages()
      ) {
        this.dataSource.paginator.firstPage();
      } else {
        this.dataSource.paginator.nextPage();
      }
    });
  }

  ngOnDestroy() {
    this.dataSourceSubscription.unsubscribe();
    this.pageSubscription.unsubscribe();
  }

  applyFilter(filterValue: string) {
    this.dataSource.filter = filterValue.trim().toLowerCase();

    if (this.dataSource.paginator) {
      this.dataSource.paginator.firstPage();
    }
  }

person SebastianG    schedule 15.10.2018    source источник
comment
Любая консоль, ошибки?   -  person SiddAjmera    schedule 15.10.2018
comment
@SiddAjmera Никаких ошибок консоли   -  person SebastianG    schedule 15.10.2018
comment
привет @SebastianG, я попытался воспроизвести вашу проблему, но работает нормально: stackblitz.com/edit/angular-j9mvpo не могли бы вы предоставить нам образец, который покажет нам вашу проблему?   -  person Yanis-git    schedule 15.10.2018
comment
привет, можешь вместо этого попробовать отказаться от подписки с условием if? Посмотрите, работает ли это, а также уверены ли вы, что ngOnDestory не отменяет подписку, потому что она завершена? Вы сказали, что делаете вызовы API, и обычно angular заботится об отписке от них.   -  person Pari Baker    schedule 15.10.2018
comment
То, что у вас есть сейчас, выглядит хорошо, поэтому проблема, вероятно, где-то в другом месте.   -  person martin    schedule 15.10.2018


Ответы (1)


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

Это означает, что ошибка должна быть какой-то глупой.

Для дальнейшего расследования проверьте:

  1. Есть ли опечатка в вашем коде?

  2. ngOnDestroy() действительно казнен? - поместите туда журнал консоли и посмотрите, действительно ли он вызывается, когда вы переключаетесь с текущей страницы. Если нет, вы, вероятно, придерживаетесь тех же правил маршрутизации, даже если страница кажется измененной.


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

this.dataSourceSubscription = mainTimer.subscribe(t => {
  this.dataSourceSubscription = this.section3.subscribe(data => {});
});
person Xinan    schedule 15.10.2018
comment
Пробовал - горит. Я думаю, что это должно быть что-то конкретное для оператора таймера rxjs. Я копался в его подписке и не мог найти, что это такое. Я исчерпал все возможности Google, и я просто не знаю, что делать дальше :( - person SebastianG; 15.10.2018
comment
this.dataSourceSubscription = timer(0, 60000).subscribe это точно такой же, как ваш реальный код? (здесь пропущены скобки) .subscribe() - person Xinan; 15.10.2018
comment
Я отредактировал свой основной пост с полным кодом oninit и ondestroy. - person SebastianG; 15.10.2018
comment
Фуууууууууу - я написал всю эту часть несколько месяцев назад и не удосужился вникнуть в то, что там происходило. Совсем пропустил. Теперь, когда я вижу это, все очевидно, спасибо! - person SebastianG; 18.10.2018
comment
это сработало для двух других подписок, которые у меня есть, НО для подписки по таймеру это сработало, только если я сначала объявил ее в приложении как «Подписка», а не «любая». Я отметил ваш ответ как правильный, но если вы можете, обновите свой ответ, включив в него часть объявления «Подписка» для бедных душ, которые попадут на эту страницу в будущем. - person SebastianG; 22.10.2018