[英]Listen to Observable.timer and emit to parent component
我有一个使用Observable.timer
的倒计时组件,该组件在父组件中使用。 使用时,它需要花费来自父组件的@Input() seconds: string
,该@Input() seconds: string
用作开始倒数的数字, ex: 60
。 现在,我想向父组件发出倒计时数字@Output() checkTime
以在按钮到达0
禁用它。
因此,我将倒计时编号订阅了checkTime
事件发射器。 但是结果是,倒数不会使它停止在0并持续递减。 谁能看到下面的问题?
register.component.html
<tr *ngFor="let course of courses">
<td>
<button class="btn btn-info" [disabled]="counter === 0"> Register</button>
</td>
<td>
<countdown [seconds]="60" (checkTime)="checkTimeExpired($event);"></countdown>
</td>
</tr>
countdown.component.ts
import { Component, Input, Output, OnInit, EventEmitter } from '@angular/core'
import { Observable, Subscription } from 'rxjs/Rx';
@Component({
selector: 'countdown',
template: '{{ countDown | async | formatTime }}'
})
export class CountdownComponent implements OnInit {
@Input() seconds: string;
@Output() checkTime: EventEmitter<number> = new EventEmitter();
countDown: any;
counter: number;
private subscription: Subscription;
constructor() {}
ngOnInit() {
this.counter = parseInt(this.seconds, 10);
this.countDown = Observable.timer(0, 1000)
.take(this.counter)
.map(() => --this.counter)
this.subscription = this.countDown.subscribe(t => {
this.checkTime.emit(this.counter)
});
}
}
register.component.ts
counter: number;
checkTimeExpired(evt) {
this.counter = evt;
}
如果我不使用订阅,则倒数计时将从0停止。
this.subscription = this.countDown.subscribe(t => {
this.checkTime.emit(this.counter)
});
抱歉,如果已经有相关问题,请帮助这个新输入的角度用户。
主要问题是您正在将Observable的值与任意变量解耦。 通常,您希望Observable流为您转换一个值-这是RxJS的一半。
问题在于.map(() => --this.counter)
。 map
运算符转换值流并返回新值。 在这里,您正在将Observable值转换为--counter
; 有问题。 --counter
将返回counter - 1
和decrement counter
,但是该值与Observable流完全分离 。 这意味着什么?
从该Observable外部控制该值会使该Observable变得炙手可热 。 它的值可以流式传输到不同的订户,但是值可以由于外部因素而改变。 (请记住,一个Observable在订阅之前不会执行)
但是...您只有一个订户,所以这不是问题,对吧? 实际上,Angular async
管道还订阅了底层的Observable。 这意味着您可观察已订阅的两倍 ,这意味着有两个定时器倒计时,这意味着有执行该两个流map
功能-这意味着每一秒, this.counter
正在递减两次 。
我建议结合Observable的计时器值和实际时间值,然后仅作为副作用发出事件:
ngOnInit() {
const start = parseInt(this.seconds, 10);
this.countDown = Observable.timer(0, 1000)
.take(start + 1) // add one, so zero is included in emissions.
.map(i => start - i) // decrement the stream's value and return
.do(s => this.checkTime.emit(s)) // do a side effect without affecting value
}
async
管道将订阅它并开始发射。 最好的部分是, async
管道在销毁销毁后会自动清理。
另一个想法是使用takeWhile
,这是一种更具声明性的方式来说明应该采取多少排放量,并在提供的表达式为false时完成:
ngOnInit() {
const start = parseInt(this.seconds, 10);
this.countdown = Observable.timer(0, 1000)
.map(i => start - i) // decrement the stream's value and return
.takeWhile(i => i >= 0)
.do(s => this.checkTime.emit(s)) // do a side effect without affecting value
}
希望这有助于消除一些困惑!
您可以尝试停止订阅的倒计时,计时器将在后台运行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.