在Angular 5中正确订阅Singleton服务

在Angular 5中正确订阅Singleton服务,angular,singleton,angular5,angular2-observables,Angular,Singleton,Angular5,Angular2 Observables,我需要一个计时器被重置,这将在每次活动后调用。因此,我创建了一个TimerService,并在其中设置了计时器 TimerService类: @Injectable() export class TimerService { timer: Observable<any>; constructor() { } setTimer(timerVal: number) { this.timer = Observable.timer(timerVal); } }

我需要一个计时器被重置,这将在每次活动后调用。因此,我创建了一个TimerService,并在其中设置了计时器

TimerService类:

@Injectable()
export class TimerService {
  timer: Observable<any>;

  constructor() { }

  setTimer(timerVal: number) {
    this.timer = Observable.timer(timerVal);
  }

}
现在,我尝试从另一个组件更新计时器的值,但它不会影响已设置的计时器

另一个组件类别:

export class AppComponent implements OnInit{
  title = 'DataBox';

  constructor(private timerService: TimerService){}

  ngOnInit() {
    this.timerService.setTimer(3000);
    this.timerService.timer.subscribe(t => {
      alert("hello");
    })
  }
}
export class AnotherComponent implements OnInit{
  users: Observable<any>;    
  constructor(private listUser: ListUserService, private timerService: TimerService) { }

  ngOnInit() {

  }

  updateTimer() {
    this.timerService.setTimer(5000);
  }

}
导出类另一个组件实现OnInit{
用户:可观察;
构造函数(私有listUser:ListUserService,私有timerService:timerService){}
恩戈尼尼特(){
}
updateTimer(){
this.timerService.setTimer(5000);
}
}
如何订阅timerService并随时更新计时器? 如何创建单例服务并订阅计时器? 但它应该只在计时器过期时发出警报,并且只发出一次警报。
我是Angular的新手,所以请容忍我。

问题是,在您的服务中,您没有用
设置计时器重置计时器,而是创建一个新的计时器。另一个组件上的订阅仍然存在于一个可观察的组件上,该组件仍然是“活动的”。您唯一更改的是
计时器
引用,因此任何新订阅都将订阅新订阅,但旧订阅仍然存在

您要做的是,在过度定义时停止第一个计时器,然后设置新的计时器。但这只能解决问题的前半部分:您的订阅仍在侦听并等待计时器。因此,您必须重新定义应用程序逻辑,以“结束”计时器,或者简单地从计时器中取消订阅

要了解如何停止可观察计时器,请阅读。基本上,您需要先在每个订阅中取消订阅()
,然后重新订阅。我将使用不同的可观察对象(例如“alertWhenNewTimerIsSet()”或其他内容)实现这一点,然后使用
subscription
s本身重新订阅新值

诸如此类: timerservice.ts:

 timer: Observable<any>;
 renewSubscriptionsAlert: new EventEmitter<any>();

 setTimer(timerVal: number) {
    timer.renewSubscriptionsAlert.emit(true);
    this.timer = Observable.timer(timerVal);
  }

顺便说一下,如果你只是需要一个计时器,你也可以使用这个方法

ForestG是正确的,您的根本错误是忽略了javaScript引用

首先,正如ForestG所说,如果您正在寻找的是一个简单的间隔,那么请使用javasScript本机间隔和clearInterval方法

如果您只想运行一个计时器,那么这是您服务中更优雅的解决方案。它通过“takeUntil”操作符创建了一个新的可观察的间隔,该间隔具有条件取消

  cancelTimer$ = new Subject();

  startTimer(interval?: number = 1000) {
    this.cancelTimer$.next();
    const timer = Observable.interval(interval);
    timer.takeUntil(this.cancelTimer$)
      .subscribe((res) => {
        console.log(res)
      },
      err => console.log(err), 
      () => {
        console.log('completed')
      })
  }
takeUnitl的优点是,我使可观察对象抛出一个“完整”事件,而simple.unsubscribe()则没有。
通过这种方式,您可以添加一个回调来处理前一个计时器。

我刚刚了解到,您询问的是计时器,而不是间隔。但是上面的代码应该对双方都适用。请告诉我们是否有任何答案适合您。
  cancelTimer$ = new Subject();

  startTimer(interval?: number = 1000) {
    this.cancelTimer$.next();
    const timer = Observable.interval(interval);
    timer.takeUntil(this.cancelTimer$)
      .subscribe((res) => {
        console.log(res)
      },
      err => console.log(err), 
      () => {
        console.log('completed')
      })
  }