Hyperapp предоставляет механизм подписок, который позволяет приложению реагировать на внешние события и интегрироваться с асинхронными источниками данных. Подписки представляют собой функции, которые вызываются после рендера и могут инициировать новые действия (actions) при наступлении определённых событий.
Подписка — это функция с сигнатурой
(dispatch, props) => cleanup, где:
dispatch — функция, используемая для отправки действий
в приложение.props — объект с параметрами подписки, передаваемый при
её подключении.cleanup — необязательная функция для удаления подписки
при уничтожении компонента или прекращении действия.Подписки позволяют работать с:
keydown, scroll,
resize;setInterval, setTimeout);Подписки добавляются в объект subscriptions при
инициализации приложения:
import { app } from "https://unpkg.com/hyperapp@2.0.15?module";
const state = { count: 0 };
const actions = {
increment: () => state => ({ count: state.count + 1 }),
decrement: () => state => ({ count: state.count - 1 })
};
const subscriptions = (state) => [
[intervalSubscription, { interval: 1000 }]
];
const intervalSubscription = (dispatch, { interval }) => {
const id = setInterval(() => dispatch(actions.increment), interval);
return () => clearInterval(id); // cleanup
};
app({ init: state, view: state => <h1>{state.count}</h1>, node: document.body, actions, subscriptions });
В этом примере подписка
intervalSubscription вызывает действие
increment каждую секунду. Функция возвращает функцию
cleanup, которая очищает таймер при удалении подписки.
Подписки особенно полезны для отслеживания внешних событий, например, нажатий клавиш или изменения размера окна:
const keySubscription = (dispatch) => {
const handler = e => {
if (e.key === "ArrowUp") dispatch(actions.increment);
if (e.key === "ArrowDown") dispatch(actions.decrement);
};
window.addEventListener("keydown", handler);
return () => window.removeEventListener("keydown", handler);
};
const subscriptions = state => [
keySubscription
];
Особенности:
cleanup гарантирует корректное удаление
слушателей, предотвращая утечки памяти.Подписки могут принимать параметры, что делает их повторно используемыми:
const resizeSubscription = (dispatch, { threshold }) => {
const handler = () => {
if (window.innerWidth < threshold) dispatch(actions.decrement);
else dispatch(actions.increment);
};
window.addEventListener("resize", handler);
return () => window.removeEventListener("resize", handler);
};
const subscriptions = state => [
[resizeSubscription, { threshold: 800 }]
];
Параметры передаются в подписку как массив [fn, props],
что позволяет использовать одну функцию подписки с разными
конфигурациями.
Подписки могут работать с асинхронными источниками данных, например WebSocket или Fetch API. Для WebSocket:
const wsSubscription = (dispatch) => {
const socket = new WebSocket("wss://example.com/socket");
socket.addEventListener("message", event => dispatch(actions.receiveMessage(JSON.parse(event.data))));
return () => socket.close();
};
const actions = {
receiveMessage: (message) => state => ({ ...state, message })
};
const subscriptions = state => [wsSubscription];
Здесь каждое входящее сообщение инициирует действие
receiveMessage, обновляя состояние приложения. Функция
cleanup закрывает соединение при уничтожении подписки.
Подписки могут реагировать на изменения состояния,
если объект subscriptions возвращает динамически
вычисляемый массив:
const subscriptions = (state) => state.enabled ? [[intervalSubscription, { interval: 1000 }]] : [];
Таким образом, подписка автоматически отключается, когда состояние изменяет условие, что позволяет динамически управлять активностью внешних слушателей.
cleanup для предотвращения
утечек ресурсов.scroll) с помощью
throttling или debouncing.Подписки в Hyperapp позволяют строить реактивное приложение, способное гибко взаимодействовать с внешним миром, сохраняя чистую архитектуру и контроль за жизненным циклом событий.