【问题标题】:Subscribing to Singleton Service properly in Angular 5在 Angular 5 中正确订阅单例服务
【发布时间】:2018-10-19 05:04:55
【问题描述】:

我需要一个计时器来重置,每次活动后都会调用它。所以我创建了一个 TimerService 并在其中设置了计时器。

TimerService 类:

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

  constructor() { }

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

}

然后我尝试订阅它,一旦计时器到期,它应该会提醒一些东西。我把这个逻辑放在 AppComponent 中,因为我需要在 Rootlevel 中订阅它。

AppComponent 类:

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);
  }

}

如何订阅 timerService 并随时更新计时器? 如何创建单例服务并订阅计时器? 但它应该只在计时器到期时发出警报,并且只有一次。 我是 Angular 新手,请多多包涵。

【问题讨论】:

  • 如果有任何答案适合您,请告诉我们。

标签: angular singleton angular5 angular2-observables


【解决方案1】:

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 的优点是 i 导致 observable 抛出“完成”事件,而简单的“.unsubscribe()”不会。 这样你就可以添加一个回调来处理前一个计时器。

【讨论】:

  • 我刚刚读到您询问的是计时器而不是间隔。但上面的代码应该适用于两者
【解决方案2】:

问题是,在您的服务中,您不要使用setTimer 重置计时器,而是创建一个新计时器。另一个组件上的订阅仍然存在于 Observable 上,它仍然是“活动的”。您唯一更改的是 timer 引用,因此任何新订阅都将订阅新订阅 - 但旧订阅仍然存在。

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

要了解如何停止可观察计时器,请阅读 this question。基本上,您需要在每次订阅中先unsubscribe(),然后再重新订阅。我会用不同的 observable 来实现(例如“alertWhenNewTimerIsSet()”或其他东西),然后使用 subscriptions 自己重新订阅新值。

类似的东西: timerservice.ts:

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

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

在你的组件中:

 mySubscription: any;

 ngOnInit() {
    this.timerService.setTimer(3000);
    this.mySubscription = this.timerService.timer.subscribe(t => {
      alert("hello");
    });
    this.timerService.renewSubscriptionsAlert(alert => {
      myTimerServiceSubscription.unsubscribe();
       this.mySubscription = this.timerService.timer.subscribe(t => {
      alert("hello");
    });
  }

顺便说一句,如果你只是需要一个计时器,你也可以使用window.setTimeout() 方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-26
    • 2019-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-25
    相关资源
    最近更新 更多