我正在尝试构建一个倒数计时器,其工作方式如下:
const startCountdown = async () => {
var countdownTime = 10;
setDisplayTime(countdownTime);
for (let i = 0; i < 10; i++) {
await sleep(1000);
countdownTime = countdownTime - 1;
setDisplayTime(countdownTime);
}
}
如您所见,该数字从10开始递减(稍后将作为用户输入)。
睡眠功能如下:
const sleep = (ms) => {
return new Promise((resolve) => setTimeout(resolve, ms));
};
问题是我希望用户能够停止计时器。我最初认为它会像这样工作:
const startCountdown = async () => {
var countdownTime = 10;
setDisplayTime(countdownTime);
for (let i = 0; i < 10; i++) {
if (timerStopped) {
break;
} else {
await sleep(1000);
countdownTime = countdownTime - 1;
setDisplayTime(countdownTime);
}
}
但是看起来新状态并没有传递到for循环中,它只是记住了函数启动时的状态。
是否有解决此问题的方法?我不需要暂停计时器并重新启动它,只需要将其停止即可(然后可以从那里重置它)。
答案 0 :(得分:1)
我为您构建了一个rxjs版本...由于可以操纵流,因此我发现此解决方案更容易一些。
const {
BehaviorSubject,
timer
} = rxjs
const {
filter,
tap,
withLatestFrom
} = rxjs.operators;
const
startButton = document.getElementById("startButton"),
pauseButton = document.getElementById("pauseButton"),
continueButton = document.getElementById("continueButton"),
stopButton = document.getElementById("stopButton");
class Timer {
_time = 0;
_timerSubscription;
_paused = new BehaviorSubject(false);
setTime(time) {
this._time = time
}
start() {
const step = 1000;
this._timerSubscription = timer(0, step).pipe(withLatestFrom(this._paused), filter(([v, paused]) => !paused)).subscribe(val => {
if (this._time <= 0) {
this.stop();
}
console.log(this._time);
this._time -= step;
});
}
pause() {
this._paused.next(true)
}
continue () {
this._paused.next(false)
}
stop() {
this.reset();
if (this._timerSubscription) {
this._timerSubscription.unsubscribe();
}
}
reset() {
this._time = 0;
}
}
const myTimer = new Timer();
myTimer.setTime(10000);
startButton.onclick = () => {
myTimer.start();
};
pauseButton.onclick = () => {
myTimer.pause();
}
stopButton.onclick = () => {
myTimer.stop();
}
continueButton.onclick = () => {
myTimer.continue();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.6.2/rxjs.umd.min.js"></script>
<button id="startButton">Start</button>
<button id="stopButton">Stop</button>
<button id="pauseButton">Pause</button>
<button id="continueButton">Continue</button>