0

I created a Observable.timer in my Ionic 2 project to countdown the time (e.g. 00:00:59->00:00:00). For example, I created the timer in a page called "PageB" and below is the typescript code:

export class PageB {
 constructor(){
this.timer = Observable.timer(500,500).map(i=>this.result-i*503).take((this.result-575999970)/503).subscribe(i => 
{
this.time=i;
console.log(i);
console.log(moment(this.time).format('HH:mm:ss'));
});
}
}

Console.log output for the above code:

Console.log output for the above code:

However, I got a problem that this timer will be duplicated when I leave from PageB to previous page and then go back to PageB again (PageB->previous page->PageB).

The duplicated situation:

enter image description here


You can see that 00:00:47, 00:00:46 and the rest are duplicated so many times. I cannot use "this.timer.unsubscribe()" to stop the timer when leaving PageB because I need it keep counting down in the background.

Therefore, could anyone tell me how to solve this problem? thanks

Tommy Mok
  • 91
  • 10
  • it kinda looks like the duplication that happens when watching for network connection where events fire twice... the suggestion for that problem was to make a service where it filters the fired events...http://stackoverflow.com/a/42454236/7266219 not sure if this gonna help.. but have a look. – Yasir Apr 11 '17 at 11:53
  • it seems not suitable in my problem.... thank you btw – Tommy Mok Apr 11 '17 at 12:40

1 Answers1

0

You could move the Observable to a provider and use Subject to ensure there is only one timer.

export class TimerProvider {
 constructor(){
}
timerSubject:Subject<any>;

loadTimer(){

Observable.timer(500,500).map(i=>this.result-i*503).take((this.result-575999970)/503).subscribe(i => 
{
this.timerSubject.next(i);
});
}

getTimer(){
 if(!this.timerSubject(){
   this.timerSubject = new Rx.Subject();
   this.loadTimer();
 }
 return timerSubject.asObservable();
}
}

In your pageB:

export class PageB {
 constructor(private timeProvider:TimerProvider){
this.timer = this.timeProvider.getTime().subscribe(i => 
{
this.time=i;
});
}
}

ngOnDestroy(){
   this.timer.unsubscribe();
}

You will have a single timer as long as your provider is singleton and it will start the first time page B is opened.

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
  • thanks for the reply. I have tried the null check but still not work...... – Tommy Mok Apr 11 '17 at 12:43
  • since it is set in the constructor.. your page is created multiple times.. maybe set `timer` as static? http://stackoverflow.com/questions/16462839/typescript-global-static-variable-best-practice – Suraj Rao Apr 11 '17 at 12:47
  • it works when using a null check and set timer as static. However, it has another problem that I cannot get the value of "this.time" variable again when I leave PageB and go back, which means I can only get the value of "this.time" when I go PageB at the 1 first time. – Tommy Mok Apr 11 '17 at 13:09
  • so even time needs to be static in that case.. not sure if it fits your use case though.. or maybe move the timer to a singleton provider/app.component? – Suraj Rao Apr 11 '17 at 13:10
  • If I cannot get the "this.time" again, I cannot show the countdown number on the UI of PageB again if I leave PageB and go back.... – Tommy Mok Apr 11 '17 at 13:11
  • to show the global variable e.g "this.time" to the front-end html in ionic is using {{time}}. So do you know how to show the static variable in this case? thanks – Tommy Mok Apr 11 '17 at 13:19
  • @TommyMok try my updated logic.. static would not be such a good idea – Suraj Rao Apr 11 '17 at 13:34
  • thanks for the updated logic. However, what should I import in my ts to get "new Rx.Subject();" work? It erros me "cannot find the name Rx" thanks – Tommy Mok Apr 12 '17 at 03:47
  • i tried the updated logic, it works for me. However, when I update the `this.result` in `Observable.timer(500,500).map(i=>this.result-i*503).take((this.result-575999970)/503).subscribe(i =>` It will have two countdown timers e.g. for the 1st timer, this.result=10, so the timer is 10..9..8; if I updated this result=11, then the timer is 11..10. However, the 1st timer is still here. So how can I stop the 1st timer and use the 2nd updated timer only? thanks – Tommy Mok Apr 12 '17 at 04:38
  • Or is it possible to have another method to make the timer in Ionic 2 project? thanks – Tommy Mok Apr 12 '17 at 04:48
  • you can save the timer subscription in the provider and unsubscribe when you want to update – Suraj Rao Apr 12 '17 at 04:48