← Назад к вопросам
Как взаимосвязаны мемоизация и кэширование?
2.0 Middle🔥 71 комментариев
#Браузер и сетевые технологии
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Мемоизация и кэширование: разные инструменты, одна цель
Мемоизация и кэширование — разные концепции, но работают в одной упряжке. Оба служат оптимизации через сохранение результатов, но применяются на разных уровнях.
Различия
Мемоизация (Memoization):
- Уровень: функция или компонент
- Область: память приложения (RAM)
- Время жизни: время сессии пользователя
- Цель: избежать пересчёта функции с одинаковыми параметрами
- Масштаб: локальная оптимизация
// Мемоизация функции
const fibonacci = (() => {
const cache = {};
return (n) => {
if (n in cache) return cache[n];
if (n < 2) return n;
cache[n] = fibonacci(n - 1) + fibonacci(n - 2);
return cache[n];
};
})();
fibonacci(100); // Быстро, результат в cache
fibonacci(100); // Мгновенно, возвращает из cache
Кэширование (Caching):
- Уровень: любой (функция, API, DOM, браузер, CDN, сервер)
- Область: памяти разных уровней (RAM, диск, сеть)
- Время жизни: настраивается (часы, дни, очистка вручную)
- Цель: избежать дорогостоящих операций (запросы, вычисления)
- Масштаб: глобальная стратегия
// Кэширование HTTP запроса
const userCache = new Map();
async function getUser(id) {
if (userCache.has(id)) {
return userCache.get(id);
}
const user = await fetch(`/api/users/${id}`).then(r => r.json());
userCache.set(id, user);
return user;
}
await getUser(123); // Запрос в сеть
await getUser(123); // Из кэша, мгновенно
Уровни кэширования в веб-приложении
Пользователь
↓
1. Браузер кэш (HTTP Cache-Control headers)
↓
2. Service Worker (PWA кэш)
↓
3. Application Layer (Redux, Zustand, React Query)
↓
4. Мемоизация функций (useMemo, useCallback)
↓
5. Network (HTTP запрос)
↓
6. CDN кэш
↓
7. Сервер Application кэш (Redis)
↓
8. Database
Примеры в React
1. useMemo — мемоизация вычислений
function Component({ items }) {
// Дорогое вычисление пересчитывается только если items изменился
const sorted = useMemo(() => {
console.log('Сортирую...');
return [...items].sort((a, b) => a - b);
}, [items]);
return <div>{sorted.length}</div>;
}
Это мемоизация — сохраняем результат сортировки.
2. useCallback — мемоизация функции
function Parent() {
const [items, setItems] = useState([]);
// Функция мемоизируется, чтобы не пересоздавалась при каждом рендере
const handleAdd = useCallback((item) => {
setItems(prev => [...prev, item]);
}, []);
// Функция не меняется (по reference) → Child не ререндерится
return <Child onAdd={handleAdd} />;
}
Это мемоизация функции в памяти.
3. React.memo — мемоизация компонента
const MemoizedList = React.memo(({ items }) => {
console.log('Рендер List');
return (
<ul>
{items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
);
});
function Parent({ items }) {
const [count, setCount] = useState(0);
return (
<>
<button onClick={() => setCount(c => c + 1)}>Count: {count}</button>
{/* List не ререндерится, если items не изменился */}
<MemoizedList items={items} />
</>
);
}
Это мемоизация компонента — если props не изменились, старый результат рендера переиспользуется.
4. HTTP кэширование (React Query)
import { useQuery } from '@tanstack/react-query';
function UserProfile({ userId }) {
// Кэширование на уровне приложения
const { data: user } = useQuery({
queryKey: ['user', userId],
queryFn: () => fetch(`/api/users/${userId}`).then(r => r.json()),
staleTime: 5 * 60 * 1000, // 5 минут
});
return <div>{user?.name}</div>;
}
// Другой компонент
function UserBio({ userId }) {
const { data: user } = useQuery({
queryKey: ['user', userId],
// Если userId 123 в кэше (свежее), запрос не происходит
});
return <p>{user?.bio}</p>;
}
Это кэширование на уровне приложения — данные с сервера хранятся в памяти.
Как они работают вместе
// Полный пример оптимизации
const expensiveCalculation = (arr) => {
// Дорогая операция: O(n²)
return arr.reduce((acc, val, i) => {
for (let j = i; j < arr.length; j++) {
acc += arr[i] * arr[j];
}
return acc;
}, 0);
};
function DataProcessor({ data }) {
// Уровень 1: Мемоизация вычисления
const memoizedResult = useMemo(() => {
return expensiveCalculation(data);
}, [data]);
// Уровень 2: Кэширование результата в localStorage (браузер)
useEffect(() => {
localStorage.setItem(
`cache_${JSON.stringify(data)}`,
memoizedResult.toString()
);
}, [memoizedResult, data]);
return <div>{memoizedResult}</div>;
}
API кэширование: практический пример
// Свой кэш с мемоизацией
class APICache {
private cache = new Map<string, { data: any; timestamp: number }>();
private ttl = 5 * 60 * 1000; // 5 минут
async fetch(url) {
const cached = this.cache.get(url);
const now = Date.now();
// Кэш ещё свежий
if (cached && now - cached.timestamp < this.ttl) {
console.log('Из кэша');
return cached.data; // Мемоизированный результат
}
// Кэш устарел — делаем запрос
console.log('Запрос в сеть');
const response = await fetch(url).then(r => r.json());
// Кэшируем результат
this.cache.set(url, {
data: response,
timestamp: now
});
return response;
}
}
const apiCache = new APICache();
await apiCache.fetch('/api/users'); // Сеть
await apiCache.fetch('/api/users'); // Кэш
// Через 5 минут
await apiCache.fetch('/api/users'); // Снова сеть
Проблемы и ограничения
Переполнение памяти (мемоизация):
// Плохо: кэш растёт без конца
const userCache = new Map();
function cacheUser(id, data) {
userCache.set(id, data); // Может заполнить всю память
}
// Хорошо: ограничиваем размер кэша (LRU cache)
class LRUCache {
constructor(maxSize = 100) {
this.maxSize = maxSize;
this.cache = new Map();
}
set(key, value) {
if (this.cache.size >= this.maxSize) {
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
this.cache.set(key, value);
}
get(key) {
return this.cache.get(key);
}
}
Инвалидация кэша:
// Когда пользователь редактирует данные, кэш устаревает
async function updateUser(id, data) {
await fetch(`/api/users/${id}`, { method: 'PUT', body: JSON.stringify(data) });
// Инвалидируем кэш
userCache.delete(id);
// Или вся история поиска
userCache.clear();
}
Итог
Мемоизация:
- Локальная оптимизация
- Сохраняет результат функции
- Время жизни: сессия
- React хуки: useMemo, useCallback, React.memo
Кэширование:
- Глобальная стратегия
- Сохраняет данные разных видов (API, DOM, локальное хранилище)
- Время жизни: настраивается (часы, дни, вечно)
- Инструменты: localStorage, sessionStorage, HTTP Cache, Redis, React Query
Вместе:
- Мемоизация = кэширование на уровне функции
- Кэширование = мемоизация на уровне приложения
- Используй оба для максимальной производительности