Я пытаюсь написать таймер обратного отсчета, который возвращает текущее значение обратного отсчета из функции. Пока мне удалось написать функцию обратного отсчета. Он ведет обратный отсчет, но функция возвращает неопределенное значение. Как я могу изменить код, чтобы вернуть значение обратного отсчета?
const startTimer = (duration, onlySeconds) => {
var timer = duration,
minutes,
seconds;
const interval = setInterval(function () {
minutes = parseInt(timer / 60, 10);
seconds = parseInt(timer % 60, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
if (timer-- === 0) {
clearInterval(interval)
}
console.info('seconds', seconds)
return !onlySeconds ? minutes + ":" + seconds : seconds;
}, 1000);
};
console.info('You will be logged out in ', startTimer(3, true))
вы ожидаете, что он вернется несколько раз?
@ПолРуни. Да, я ожидал, что он будет возвращать данные каждую секунду.
Возврат работает не так. Он просто возвращается один раз, а затем завершается. Вам нужно использовать асинхронные механизмы, такие как обратные вызовы или промисы. Ответы, предоставленные до сих пор, кажутся довольно хорошими.
Вы не можете вернуться из асинхронного обратного вызова setInterval
и ожидать доступа к этому возвращаемому значению. Вместо этого я мог бы порекомендовать передать функцию logger
, которой вы можете передать количество оставшегося времени. В этой функции вы можете делать с этим временем все, что захотите. Вот версия, которая просто ведет журнал консоли.
const startTimer = (duration, onlySeconds, logger) => {
var timer = duration,
minutes,
seconds;
const interval = setInterval(function () {
minutes = parseInt(timer / 60, 10);
seconds = parseInt(timer % 60, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
if (timer-- === 0) {
clearInterval(interval)
}
const time = !onlySeconds ? minutes + ":" + seconds : seconds;
logger(time);
}, 1000);
};
const logger = (time) => {
console.info('You will be logged out in ' + time);
}
startTimer(300, false, logger)
это намного проще и прямо в точку
const startTimer = (duration, onlySeconds) => {
var timer = duration,
minutes,
seconds;
const interval = setInterval(function () {
minutes = parseInt(timer / 60, 10);
seconds = parseInt(timer % 60, 10);
minutes = minutes < 10 ? "0" + minutes : minutes;
seconds = seconds < 10 ? "0" + seconds : seconds;
if (timer-- === 0) {
clearInterval(interval)
}
console.info('You will be logged out in '+ (!onlySeconds ? minutes + ":" + seconds : seconds));
}, 1000);
};
startTimer(3, true);
Я думаю, что другая стратегия может быть в порядке.
class Countdown {
constructor() {
this._init();
}
_init(restart=false) {
this.target = undefined;
this.running = false;
this.terminate = false;
if (!restart) {
this.ms = undefined;
this.tick = [];
this.done = [];
}
}
// Set a callback that is called every second. `fn(remaining)`
ontick(fn) {
this.tick.push(fn);
}
// Set a callback that is called when the countdown ends. `fn()`
ondone(fn) {
this.done.push(fn);
}
// Start countdown with duration in milliseconds
start(ms) {
const now = performance.now();
if (this.running) throw new Exception('Countdown already running.');
this.running = true;
this.ms = ms;
this.target = now + ms;
this.update = () => {
const now = performance.now();
if (this.terminate) {
this._init();
return;
}
const remaining = this.target - now;
if (remaining > 100) {
setTimeout(this.update, remaining % 1000);
this.tick.forEach(fn => fn(remaining));
}
else {
this.done.forEach(fn => fn());
this._init();
}
};
setTimeout(this.update, this.target % 1000);
}
// Restart a running countdown. Optionally provide a new duration.
restart(ms=this.ms) {
const now = performance.now();
if (!this.running) throw new Exception('Countdown not running.');
this.ms = ms;
this.target = now + ms;
}
// Stop a running countdown.
stop() {
if (!this.running) throw new Exception('Countdown not running.');
this.terminate = true;
}
}
Тогда вы будете использовать его следующим образом:
const countdown = new Countdown();
countdown.ontick(remaining => {
console.info('Remaining:', remaining, 'ms');
});
countdown.ondone(() => {
console.info('Countdown completed.');
});
countdown.start(15*60*1000); // 15 minutes
Если вы хотите перезапустить текущий обратный отсчет:
countdown.restart(5*60*1000); // Update target duration to 5 minutes and restart
countdown.restart(); // Use previous duration and restart
Если вы хотите отменить обратный отсчет:
countdown.stop();
Вы не знаете, правда. Вы делаете то же самое, что и с первым
console.info()
, но вместо этого обновляете страницу.