Promise VS setInterval
Сразу скажу, прогаю как любитель, все не срочно и не критично.
Но хотелось бы сделать вот что. Разбираю свои небольшие математические скетчи на JS. Там вся анимация на setInterval/clearInterval.
Пример. Пусть:
isPlay - флаг проигрывания
delay - задержка
calculateNewState() - некие вычисления
showCanvas() - отображение
Вычисления достаточно долгие, отображение быстрое.
delay выбирается, чтобы в любом случае быть больше времени работы этих функций. И такой код:
function step()
{
timerId = setInterval(function() {
if (! isPlay) {
clearInterval(timerId);
return;
}
calculateNewState();
showCanvas();
if (! isPlay) clearInterval(timerId);
}, delay);
}
Работает, при слишком малом delay запинается, но не критично.
И все же хочется сделать это грамотно и без запинок. Для этого, очевидно, и нужны промисы. В целом в них разобрался, сделал даже такой пример. Но как перейти от setInterval к промисам, никак не пойму ((
UPD
Уточняю формулировку. Выполнение calculateNewState() + showCanvas() должно занимать минимум delay сек. Если оно меньше - значит мы ждем оставшееся до delay время и начинаем новый цикл.
А если оно получается больше, тогда дожидаемся корректного завершения функций, и сразу начинаем новый цикл.
Думаю async-await для этого и созданы, но сложно найти примеры такого прямого применения.
Функции простые, вычисление массива и его отображение, внутри них нет ни интерфейса, ни setInterval ни async.
Ответы (2 шт):
Но как перейти от setInterval к промисам, никак не пойму ((
Из приведенного можно сделать нечто такое...
let isPlay = true
const delay = 1000
step()
.then(_ => console.log('Все'))
.catch(console.log)
//
async function step() {
while (isPlay) {
await calculateNewState(2000),
await showCanvas(1000)
console.log('Шаг')
}
}
document.querySelector('button').addEventListener('click', _ => isPlay = false)
//
async function calculateNewState(delay) {
await new Promise(res => setTimeout(_ => {
console.log('calculateNewState завершен')
res()
}, delay));
}
//
async function showCanvas(delay) {
await new Promise(res => setTimeout(_ => {
console.log('showCanvas завершен')
res()
}, delay));
}
<button>Стоп</button>
Ура, получилось, спасибо всем за советы!
async function sleep(delay) {
return new Promise(resolve => {
setTimeout(() => {
calculateNewState();
showCanvas();
resolve()
}, delay);
})
}
async function step(delay) {
while (isPlay) {
await sleep(delay)
}
}
Отображается гораздо плавнее (к слову сказать, у меня delay около 40-50 мс),
жаль не получается GIF вставить.