【问题标题】:ngrx observable timer angular 5ngrx 可观察计时器角度 5
【发布时间】:2018-04-13 04:58:25
【问题描述】:

我是 Angular 和 ngrx 的新手。我正在构建一个与 Todoist api 集成的番茄钟计时器应用程序。我使用了 [ngrx/platform 示例应用程序作为入门应用程序] (https://github.com/ngrx/example-app),它使用带有组件的容器。我最初在纯 rxjs 中创建了一个计时器,它可以自己运行。我目前正在尝试将计时器从与选定任务页面结合使用的 taskDetail 页面集成到我的代码中。有一个播放/暂停按钮应该与它各自的动作一致。计时器播放并暂停,但剩余时间显示不正确。我假设是因为我没有订阅计时器和/或以我应该的方式传递时间。这些按钮都调用与输出到 selected-task-page.ts 相同的函数,它具有 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>

 

上述模板具有以下输入和输出:

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


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

**在我的 selected-task-page.ts 模板代码中,我有:

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

我有以下然后调用服务。**

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

调用:

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

在我的 pomo-timer.ts 中,我有以下内容

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

timer$ = this.timerSource.asObservable();

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

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

然后我在 pomo-timer.ts 中也有计时器功能:

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

这个想法是,当用户单击播放按钮时,计时器开始倒计时并显示剩余时间,以及暂停按钮何时暂停。我的一个问题是我应该订阅 timer$ 还是应该订阅 timerRemaining 然后我如何订阅它以便它可以进入 Input 并在倒计时时显示剩余时间最后我什至需要获取和设置状态的功能吗?

感谢我能得到的任何帮助。先感谢您。

【问题讨论】:

  • 你有推送到的 github repo 吗?在那里或在 stackblitz 上调试会更容易。
  • 模板中不用this,直接调用ts变量即可。例如将[timeRemaining]="this.pomoTimerService.timeRemaining" 更改为[timeRemaining]="pomoTimerService.timeRemaining"
  • 刚刚将所有更改推送到我的仓库:(github.com/djr-taureau/pomodoro-it)。原谅我,我熟悉 stackblitz 但不知道如何将我的项目上传到其中。
  • 想出了如何轻松地从 github 上传到 stackblitz。它在 stackblitz 上:(stackblitz.com/github/djr-taureau/pomodoro-it)

标签: angular ngrx


【解决方案1】:

以下是开始/暂停的方法:

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

【讨论】:

  • 感谢您为计时器 @buzz 提供这个非常简单明了的解决方案,但由于组件的交互,我仍在努力正确地实现它。 task-detail 将按钮单击作为输出传递给 selected-task-page.ts 传递给 pomo-timer.ts (定时器服务) 我将您的代码放入定时器服务并让它传递给定时器订阅被接收为原始调用页面 task-detail.ts 的输入,但我无法输出任何内容,也没有收到任何错误
猜你喜欢
  • 2017-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-23
  • 1970-01-01
  • 1970-01-01
  • 2019-11-04
  • 2019-03-24
相关资源
最近更新 更多