Hyperapp — это лёгкий фронтенд-фреймворк для построения реактивных пользовательских интерфейсов на JavaScript. Несмотря на минимализм, он обеспечивает мощные средства для управления состоянием и реакциями на события, включая работу с таймерами и временными операциями. Таймеры позволяют создавать отложенные действия, периодические обновления данных и анимации, интегрированные с состоянием приложения.
В Hyperapp таймеры чаще всего используются через эффекты (effects), которые позволяют отделить побочные действия от чистого состояния. Эффект — это функция, принимающая аргументы и возвращающая функцию, которая выполняется после обновления состояния.
const delayEffect = (ms, action) => (dispatch) => {
setTimeout(() => dispatch(action), ms);
};
Здесь delayEffect принимает задержку в миллисекундах и
действие (action), которое нужно выполнить через заданное
время. Функция возвращает другую функцию, которая получает
dispatch и инициирует таймер. Такой подход полностью
соответствует концепции Hyperapp: побочные эффекты управляются
централизованно и не смешиваются с чистым состоянием.
setIntervalДля создания повторяющихся операций используется стандартный
setInterval. В Hyperapp его удобно интегрировать через
эффекты:
const intervalEffect = (ms, action) => (dispatch) => {
const id = setInterval(() => dispatch(action), ms);
return () => clearInterval(id);
};
Пример использования с простым счётчиком:
const state = { count: 0 };
const actions = {
tick: () => (state) => ({ count: state.count + 1 }),
startTimer: () => (state, actions) => intervalEffect(1000, actions.tick)
};
Каждую секунду состояние увеличивается на единицу, и компонент автоматически ререндерится.
Иногда нужно иметь возможность остановить таймер вручную. Для этого состояние может хранить идентификатор таймера:
const state = { count: 0, timerId: null };
const actions = {
start: () => (state, actions) => ({
timerId: setInterval(() => actions.tick(), 1000)
}),
stop: (state) => {
clearInterval(state.timerId);
return { timerId: null };
},
tick: (state) => ({ count: state.count + 1 })
};
requestAnimationFrameДля плавной анимации лучше использовать
requestAnimationFrame, так как он синхронизирован с
обновлением экрана:
const animationEffect = (update) => (dispatch) => {
let running = true;
const loop = () => {
if (!running) return;
dispatch(update);
requestAnimationFrame(loop);
};
requestAnimationFrame(loop);
return () => { running = false; };
};
requestAnimationFrame
вызывает функцию перед следующим ререндером браузера, обеспечивая
высокую производительность.running
позволяет останавливать анимацию в любой момент, интегрируя её с
жизненным циклом компонента.Пример использования с движущимся объектом:
const state = { x: 0 };
const actions = {
move: (state) => ({ x: state.x + 2 }),
startMove: () => (state, actions) => animationEffect(actions.move)
};
Объект будет плавно двигаться по горизонтали, обновляясь синхронно с кадрами браузера.
Hyperapp позволяет комбинировать таймеры и анимации для более сложных сценариев:
Пример пошаговой анимации:
const state = { step: 0 };
const actions = {
nextStep: (state) => ({ step: state.step + 1 }),
startSteps: () => (state, actions) => {
const steps = [500, 1000, 1500];
steps.forEach((ms, index) => {
setTimeout(() => actions.nextStep(), ms);
});
}
};
Эффекты таймеров и анимаций должны корректно взаимодействовать с жизненным циклом компонентов:
Пример интеграции с компонентом:
const TimerComponent = ({ interval }) => (state, actions) => ({
oncreate: () => intervalEffect(interval, actions.tick)
});
Таймер будет автоматически запускаться при создании компонента и прекращаться при его удалении.
requestAnimationFrame обеспечивает плавность обновлений и
минимальную нагрузку на процессор.Hyperapp предоставляет все необходимые механизмы для точного контроля времени в приложении, объединяя чистое состояние и побочные эффекты в единую архитектуру, что позволяет создавать как простые таймеры, так и сложные анимации и последовательные операции.