【问题标题】:Angular6 rxjs unsubscribing to timer subscription OnDestroy does not work?Angular6 rxjs 取消订阅定时器订阅 OnDestroy 不起作用?
【发布时间】:2018-10-15 13:04:17
【问题描述】:

所以我有一个计时器,我每 60 秒调用一次 api(它是一个数字标牌应用程序,所以不会有任何交互,但我希望它自动更新)

我有各种组件可以加载不同的 api 调用,但问题是,当我尝试取消订阅这些计时器订阅 ondestroy 时,它根本不起作用。

我进去,通过路由到 2 个组件来回测试 5-6 次。每次我去下一个时,这通常会终止订阅。

60 秒过去后,我在这两者之间切换的次数与我进行的次数一样多。所以我每次使用其中一个组件时都创建了一个计时器订阅,但没有销毁它们。

编辑,在下面添加了我完整的 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();
    }
  }

【问题讨论】:

  • 任何控制台,错误?
  • @SiddAjmera 没有任何控制台错误
  • 嗨 @SebastianG 我已经尝试重现您的问题,但工作正常:stackblitz.com/edit/angular-j9mvpo 您能否提供向我们展示您的问题的示例?
  • 嗨,您可以尝试使用 if 条件取消订阅吗?看看这是否有效,您还确定 ngOnDestory 没有取消订阅,因为它完成了吗?你说你正在做 Api 调用,通常 Angular 会负责取消订阅它们。
  • 你现在看起来不错,所以问题可能出在其他地方

标签: angular rxjs angular6 angular2-observables rxjs6


【解决方案1】:

因此,根据您在问题中的描述,一般来说,我认为您订阅和取消订阅 observable 的方式没有任何问题。

这意味着错误一定是愚蠢的。

要进一步调查,请检查:

  1. 你的代码有错别字吗?

  2. ngOnDestroy() 真的被执行了吗? - 在那里放置一个控制台日志,看看当你离开当前页面时它是否真的被调用。如果没有,即使页面似乎已更改,您也可能会保持相同的路由规则。


订阅被覆盖,因此不再指向计时器。当您销毁(取消订阅)它时,它实际上是取消订阅内部可观察对象,而不是计时器可观察对象。

this.dataSourceSubscription = mainTimer.subscribe(t => {
  this.dataSourceSubscription = this.section3.subscribe(data => {});
});

【讨论】:

  • 试过了——确实火了。我认为它必须是 rxjs 计时器操作员特有的东西。我一直在挖掘它的订阅,但找不到它是什么。我已经用尽了所有谷歌的可能性,我只是不知道下一步该做什么:(
  • this.dataSourceSubscription = timer(0, 60000).subscribe 与您的实际代码完全相同吗? (此处缺少括号).subscribe()
  • 我用完整的 oninit 和 ondestroy 代码编辑了我的主帖
  • Fuuuuuuuuuu -- 我几个月前写了整个部分,并没有费心去真正经历那里发生的事情。完全错过了。现在我看到了,这一切都很明显,谢谢!
  • 这对我拥有的其他两个订阅有效,但对于计时器订阅,它只有在我首先在应用程序中将其声明为“订阅”而不是“任何”时才有效。我已将您的答案标记为正确,但如果可以,请更新您的答案,以包括将来登陆此页面的可怜灵魂的“订阅”声明部分。
猜你喜欢
  • 1970-01-01
  • 2020-05-27
  • 2023-03-23
  • 1970-01-01
  • 2021-11-18
  • 1970-01-01
  • 2017-03-26
  • 2020-10-28
  • 2017-08-24
相关资源
最近更新 更多