В жизни каждого инженера-фронтендера наступает момент, когда осознаёшь: далее не обойтись без кэширования данных из API. Всё может начаться с самых невинных вещей: сохраняем предыдущую страницу с данными, чтобы кнопка «Назад» срабатывала мгновенно; реализуем простенькую логику отмены действия или обеспечиваем слияние нескольких состояний от различных запросов к API. Но все мы знаем, чем такое кончается. Один за другим возникают запросы на новые фичи, и вскоре мы уже не покладая рук реализуем кэши данных, индексы для работы вручную, оптимистические мутации и рекурсивную инвалидацию кэша.
Эти фичи явственно смахивают на внутренние механизмы баз данных. Действительно, в любом достаточно сложном клиентском приложении программисту непременно придётся реализовывать такое множество фич для управления данными, что эта работа будет напоминать построение предметно-ориентированной базы данных. Такая дополнительная сложность удваивается в каждом проекте, над которым мы работаем, поэтому приходится тратить время на решение бизнес-проблем, а радовать пользователя – уже как успеем.
Поэтому сегодня предлагаю вам составить мне компанию – и мы вместе рассмотрим распространённые паттерны работы с данными приложений, а также разберёмся, как они соотносятся с фичами баз данных. Далее мы рассмотрим решения, которые могли бы стать альтернативами этим паттернам – например, как сделать в клиентской части оптимизированный стек базы данных, который позволил бы нам сосредоточиться на разработке приложения, а не на мелкой возне с данными.
Добро пожаловать в мир эпизодического программирования баз данных.
Простенький кэш
Наше путешествие начнётся максимально скучным образом. Отправляем запрос от API на сервер и сохраняем его в локальной переменной. Потребность поступить так может возникнуть по целому ряду причин, но вот вам хороший пример: допустим, нужно как-то обогнуть декларативные механизмы повторного отображения. Во многих современных веб-приложениях используются декларативные фреймворки, например, React, которые в силу самого своего внутреннего устройства по три раза отображают одни и те же рисунки, пока пользователь работает со страницей. Конечно же, нам не хочется выполнять запрос к API при каждой такой операции рендеринга – поэтому забрасываем эти данные в переменную. Вот пример с использованием React-хуков:
const Newsfeed = () => {
const [{ loading, entries, error }, setEntries] = useState({
loading: true,
entries: [],
error: null,
});
useEffect(() => {
NewsfeedAPI.getAll()
.then((entries) => setEntries({entries }))
.catch((error) => setEntries({ error }));
}, []);
// отобразить загрузку, записи и состояния ошибок
return <div>...</div>;
};Для большей ясности этот пример упрощён. Лучше так не делайте, а пользуйтесь проверенными в боях библиотеками API, либо продолжайте штудировать источники о базах данных, оптимизированных для работы с клиентской частью!
