ngrx observable timer angular 5

蓝咒 提交于 2019-12-10 12:18:32

问题


I am very much a newbie to angular and ngrx. I am building a pomodoro timer app that integrates with the Todoist api. I have used the the [ngrx/platform example app as a starter app] (https://github.com/ngrx/example-app) which uses containers with components. I originally created a timer in pure rxjs that functions as it should on it's own. I am currently trying to integrate the timer into my code from a taskDetail page that works in conjunction with a selected-task page. There is a play/pause button that should should behave with it's respective actions. The timer plays and pauses but the time remaining is not displaying correctly. I am assuming because i am not subscribing to the timer and/or passing to the time the way in which i should. The buttons all call the same function as output to selected-task-page.ts which has a provider of pomo-timer-service.ts

task-detail.ts

timeRemaining: any;
private timerSubscription: Subscription;

constructor(public pomoTimerService: PomoTimerService, private store: 
 Store<fromTasks.State>) {
 this.task$ = store.pipe(select(fromTasks.getSelectedTask));
 this.isSelectedTaskInCollection$ = store.pipe(
  select(fromTasks.isSelectedTaskInCollection)
 );
 this.timerSubscription = this.pomoTimerService.getState().subscribe(
  timeRemaining => {
    this.timeRemaining = timeRemaining;
   }
  );
}

<button id="resume" name="resumeButton" class="resume-btn"
mat-raised-button color="primary" (click)="resumeCommand($event)"><i class="material-icons">play_arrow</i></button>
<button id="pause" name="pauseButton" class="pause-btn"
mat-raised-button color="primary" (click)="resumeCommand($event)"><i class="material-icons">pause</i></button>

 

The above template has as inputs and outputs the following:

@Input() timeRemaining: number;
@Input() timerSubscription: Subscription;
@Output() resumeClicked = new EventEmitter();


resumeCommand(action: any) {
 this.resumeClicked.emit(action);
 }

**Within my selected-task-page.ts template code I have:

<bc-task-detail
  [timeRemaining]="this.pomoTimerService.timeRemaining"
  [pomoTitle]="this.pomoTimerService.pomoTitle$"
  [pomoCount]="this.pomoTimerService.pomoCount$"
  (resumeClicked)="resumeClicked($event)"
  (resumeClicked)="resumeClicked($event)">
 </bc-task-detail>

I have the following which then calls the service.**

(resumeClicked)="resumeClicked($event)"
(resumeClicked)="resumeClicked($event)"

which calls:

resumeClicked(event) {
 console.log(event);
 console.log(event.target);
 console.log(event.srcElement);
 console.log(event.type);
 console.log(event.currentTarget.attributes.name.nodeValue);
 console.log(event.currentTarget.attributes.id.nodeValue);
 this.pomoTimerService.startTimer(event);
 }

Within my pomo-timer.ts I have the following

private timerSource = new Subject<any>();
timeRemaining;

timer$ = this.timerSource.asObservable();

setState(state: any) {
 this.timerSource.next(state);
}

getState(): Observable<any> {
 return this.timerSource.asObservable();
}

Then i have the timer function in the pomo-timer.ts as well:

  startTimer(event) {
   this.buttonState = event.currentTarget.attributes.name.nodeValue;
   this.buttonAction = event.currentTarget.attributes.id.nodeValue;
   this.timerToggle = (this.buttonAction === 'resume') ? true : false;
   const resumeButton = document.getElementById('resume');
   const pauseButton = document.getElementById('pause');
   const resetButton = document.getElementById('reset');
   const interval$: any = interval(1000).pipe(mapTo(-1));
   const pause$ = fromEvent(pauseButton, 'click').pipe(mapTo(false));
   const resume$ = fromEvent(resumeButton, 'click').pipe(mapTo(true));

  const timer$ = merge(pause$, resume$).pipe(
   startWith(interval$),
   switchMap(val => (val ? interval$ : empty())),
   scan((acc, curr) => (curr ? curr + acc:acc),this.countdownSeconds$),
   takeWhile(v => v >= 0),
   )
   .subscribe(
     val => { this.timeRemaining = val; },
     () => {
     this.resetTimer();
    });
   }

The idea was that when the user clicks the play button the timer begins counting down and displaying the remaining time as it does so and when the pause button would pause it. One of my questions is should I be subscribing to timer$ or should I be subscribing to timerRemaining and then how do I subscribe to that so that it can go into the Input and display the remaining time as it is counting down and lastly do I even need to functions for getting and setting state?

I appreciate any help I can get. Thank you in advance.


回答1:


Here is how you could start / pause:

let defaultTime = 2;
let newTime;
let $interval;


const interval$ = Rx.Observable.timer(0, 1000).map(_ => {
  return _ <= defaultTime ? defaultTime - _ : $interval.unsubscribe();
});

function start() {
  $interval = interval$.subscribe(_ => {
    newTime = _;
    console.log(_);
  });
}

function pause() {
  $interval.unsubscribe();
  defaultTime = newTime - 1;
}

document.getElementById('btn').addEventListener('click', start)
document.getElementById('btn2').addEventListener('click', pause)

DEMO



来源:https://stackoverflow.com/questions/49804112/ngrx-observable-timer-angular-5

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!