Правильная подписка на Singleton Service в Angular 5 - PullRequest
0 голосов
/ 09 мая 2018

Мне нужно сбросить таймер, который будет вызываться после каждого действия. Поэтому я создал TimerService и установил таймер внутри него.

Класс TimerService:

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

  constructor() { }

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

}

Затем я попытался подписаться на него, и как только таймер истечет, он должен что-то предупредить. Я поместил эту логику в AppComponent, так как мне нужно подписаться на нее в корневом уровне.

Класс 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 и обновлять таймер в любое время? Как мне создать Singleton Service и подписаться на таймер? Но он должен предупреждать только когда истекает таймер и только один раз. Я новичок в Angular, так что, пожалуйста, потерпите меня.

Ответы [ 2 ]

0 голосов
/ 09 мая 2018

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 состоит в том, что я заставляю наблюдаемое генерировать «завершенное» событие, а простое «.unsubscribe ()» - нет. Таким образом, вы можете добавить обратный вызов для обработки предыдущего таймера.

0 голосов
/ 09 мая 2018

Проблема в том, что в вашем сервисе вы не сбрасываете таймер с setTimer, а создаете новый. Подписка на другой компонент все еще существует в Observable, который все еще "жив". Единственное, что вы изменили, - это ссылка timer, поэтому любые новые подписки будут подписываться на новую, но старые подписки все равно будут существовать.

Что вы хотите сделать, это остановить первый таймер при переопределении, а затем установить новый таймер. Но это решило бы только первую половину вопроса: ваши подпитки все равно будут слушать и ждать таймера. Таким образом, вы должны переопределить логику своего приложения, «завершить» таймеры или просто отписаться от них.

Чтобы увидеть, как остановить наблюдаемый таймер, прочитайте этот вопрос . По сути, вам нужно unsubscribe() сначала в каждой отдельной подписке , а затем повторно подписаться. Я достиг бы этого с другой наблюдаемой (например, «alertWhenNewTimerIsSet ()» или чем-то еще), а затем повторно подписался бы на новое значение, используя сами subscription.

что-то вроде этого: 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 () .

...