3

So I have a timer where I call an api every 60 seconds (it's a digital signage app so there won't be any interaction yet I want it to auto update)

I have various components that load different api calls but the problem is, when I'm trying to unsubscribe to these timer subscriptions ondestroy it simply does not work.

I go in, test by routing to 2 components back and forth 5-6 times. This should normally kil subscription everytime I go to the next one.

After 60 seconds passes, there's as many api calls being made as many times I've switched between those two. so I've created a timer subscription everytime I went on one of the components but did not destroy them.

EDIT, added my full OnInit and OnDestroy code below:

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();
    }
  }
SebastianG
  • 8,563
  • 8
  • 47
  • 111
  • Any console, errors? – SiddAjmera Oct 15 '18 at 13:11
  • @SiddAjmera No console errors whatsoever – SebastianG Oct 15 '18 at 13:18
  • hi @SebastianG i have try to reproduce your issue but is working fine : https://stackblitz.com/edit/angular-j9mvpo could you provide us sample who show us your issue ? – Yanis-git Oct 15 '18 at 13:20
  • hi, can you try unsubscribing with an if condition instead? See if that works, also are you sure the ngOnDestory isnt unsubscribing because it hits complete? You said you are making Api calls, and usually angular takes care of unsubscribing from them. – Pari Baker Oct 15 '18 at 13:52
  • What you have now looks good so the problem is probably somewhere else – martin Oct 15 '18 at 14:18

1 Answers1

2

So from what you described in the question, generally speaking, I don't think there is anything wrong with how you subscribe & unsubscribe the observable.

Which means the mistake must be something silly.

To investigate further, please check:

  1. Is there any typo with your code?

  2. Is ngOnDestroy() really executed? - put a console log there and see if it really gets called when you switch away from your current page. If not, you probably staying the same route rules even if the page seems to be changed.


The subscription gets overwritten so it's no longer pointing to the timer. When you destroy (unsubscribe) it, it's actually unsubscribe the inner observable, not the timer observable.

this.dataSourceSubscription = mainTimer.subscribe(t => {
  this.dataSourceSubscription = this.section3.subscribe(data => {});
});
Xinan
  • 3,002
  • 1
  • 16
  • 18
  • Tried -- it does fire. I think it must be something specific to rxjs timer operator. I've been digging through its subscription and couldn't find what it is. I've exhausted all google posibilities and I just don't know what to do next :( – SebastianG Oct 15 '18 at 16:37
  • `this.dataSourceSubscription = timer(0, 60000).subscribe` is it exactly the same as your actual code? (missing brackets here) `.subscribe()` – Xinan Oct 15 '18 at 16:41
  • I have edited my main post with full oninit and ondestroy code – SebastianG Oct 15 '18 at 16:44
  • Fuuuuuuuuuu -- I wrote that whole part some months ago and didn't bother to actually go through what was happening there. Completely missed it. Now that I see it it's all obvious, thanks! – SebastianG Oct 17 '18 at 22:28
  • that has worked for the other two subscriptions I have BUT for the timer subscription it only worked if I first declared it in the app as 'Subscription' instead of 'any'. I have marked your answer as right but if you can please do update your answer to include the 'Subscription' declaration part for the poor souls that land on this page int he future. – SebastianG Oct 22 '18 at 11:30