← Назад к вопросам
Как закэшировать данные в useAsyncData?
1.0 Junior🔥 131 комментариев
#Браузер и сетевые технологии
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Кэширование данных в useAsyncData (Nuxt)
Я в основном работаю с React, но useAsyncData — это композабл из Nuxt 3 для загрузки асинхронных данных с встроенным кэшированием. Вот полный гайд.
Базовое использование useAsyncData
// pages/user/[id].vue
<script setup lang="ts">
const route = useRoute();
const userId = route.params.id as string;
const { data: user, pending, error } = await useAsyncData(
`user-${userId}`, // ключ кэша (уникальный идентификатор)
() => $fetch(`/api/users/${userId}`) // функция для загрузки
);
</script>
<template>
<div>
<div v-if="pending">Loading...</div>
<div v-else-if="error">Error: {{ error.message }}</div>
<div v-else>
<h1>{{ user.name }}</h1>
<p>{{ user.email }}</p>
</div>
</div>
</template>
Этот код автоматически кэширует результат с ключом user-{userId}.
Как работает кэш в useAsyncData
1. Ключ кэша обязателен
// ✓ ПРАВИЛЬНО: уникальный ключ кэша
const { data } = await useAsyncData('products-list', () => fetchProducts());
// ✗ НЕПРАВИЛЬНО: нет ключа кэша
const { data } = await useAsyncData(null, () => fetchProducts());
Ключ должен быть:
- Уникальным для каждого запроса
- Консистентным (всегда один и тот же для одних данных)
- Описательным (понимаем, что это кэш)
2. Динамические ключи
// Для динамических данных — включай переменные в ключ
const route = useRoute();
const userId = route.params.id;
const filter = route.query.filter;
const { data: user } = await useAsyncData(
`user-${userId}-${filter}`, // включаем переменные
() => $fetch(`/api/users/${userId}?filter=${filter}`)
);
// Причина: если меняется userId, нужен новый ключ
// Иначе будут показаны старые кэшированные данные
3. Кэширование на сервере и клиенте
// Nuxt 3 использует payload extraction
const { data, refresh } = await useAsyncData(
'products',
async () => {
return await $fetch('/api/products');
},
{
server: true, // выполнить на сервере (SSR)
// Результат попадёт в payload.json и будет переиспользован на клиенте
}
);
// На сервере: запрос выполнится
// На клиенте: данные возьмут из payload.json, новый запрос не будет
Опции useAsyncData
1. watch — пересчитывать при изменении
const userId = ref('1');
const { data: user } = await useAsyncData(
`user-${userId.value}`,
() => $fetch(`/api/users/${userId.value}`),
{
watch: [userId] // перезагрузить при изменении userId
}
);
// Когда userId меняется:
// 1. Nuxt видит изменение через watch
// 2. Видит, что ключ кэша изменился (user-1 -> user-2)
// 3. Запрашивает новые данные
// 4. Кэширует под новым ключом
2. pick — выбрать свойства из ответа
const { data } = await useAsyncData(
'user',
() => $fetch('/api/user'),
{
pick: ['id', 'name', 'email'] // кэширует только эти поля
// остальное (address, phone) не попадёт в payload
}
);
3. transform — трансформировать данные
const { data: formattedUser } = await useAsyncData(
'user',
() => $fetch('/api/user'),
{
transform: (data) => ({
...data,
displayName: `${data.firstName} ${data.lastName}`,
isAdmin: data.role === 'admin'
})
}
);
// Кэшируются трансформированные данные
4. dedupe — дедубликация запросов
// Если несколько компонентов одновременно запрашивают одни данные
const { data: users } = await useAsyncData(
'users',
() => $fetch('/api/users'),
{
dedupe: 'cancel' // отменить дубликаты запросов
// вместо 3 запросов будет 1
}
);
Управление кэшем вручную
1. Функция refresh() — пересчитать данные
const { data, refresh, pending } = await useAsyncData(
'products',
() => $fetch('/api/products')
);
const handleRefresh = async () => {
// Пересчитать данные (игнорируя кэш)
await refresh();
};
2. clear() — очистить кэш
const { clear } = await useAsyncData('products', () => fetchProducts());
// Где-то в приложении
const handleClearCache = () => {
clear(); // кэш удалён, следующий вызов будет запрос
};
3. useAsyncData vs $fetch
// useAsyncData — с кэшем и SSR
const { data } = await useAsyncData('products', () => $fetch('/api/products'));
// $fetch — просто запрос, без кэша
const data = await $fetch('/api/products');
// Используй useAsyncData для:
// - Данных, которые используются в нескольких компонентах
// - SSR (рендеринг на сервере)
// - Кэширования результатов
// Используй $fetch для:
// - One-time запросов
// - Отправки данных (POST, PUT)
// - Когда кэш не нужен
Практические примеры
Пример 1: Список товаров с фильтром
<script setup lang="ts">
const route = useRoute();
const category = computed(() => route.query.category as string);
const sort = computed(() => route.query.sort as string);
const { data: products, refresh } = await useAsyncData(
() => `products-${category.value}-${sort.value}`, // динамический ключ
() => $fetch('/api/products', {
query: { category: category.value, sort: sort.value }
}),
{
watch: [category, sort] // пересчитать при изменении
}
);
</script>
<template>
<div>
<FilterPanel @change="refresh" />
<ProductList :products="products" />
</div>
</template>
Пример 2: Глобальный кэш (composable)
// composables/useProducts.ts
export const useProducts = () => {
return useAsyncData(
'products-list', // один ключ для всех компонентов
() => $fetch('/api/products'),
{
server: true // кэширует на сервере
}
);
};
// components/ProductList.vue
<script setup lang="ts">
const { data: products } = await useProducts();
// Если несколько компонентов используют этот composable,
// они получат данные из одного кэша
</script>
Пример 3: Инвалидация кэша после мутации
const { data: user, refresh } = await useAsyncData(
'current-user',
() => $fetch('/api/user')
);
const handleUpdateProfile = async (updates) => {
await $fetch('/api/user', {
method: 'PUT',
body: updates
});
// Инвалидировать кэш и пересчитать
await refresh();
};
Пример 4: Nested data с кэшем
// Сложная структура данных
const { data } = await useAsyncData(
'dashboard',
async () => {
const [user, stats, settings] = await Promise.all([
$fetch('/api/user'),
$fetch('/api/stats'),
$fetch('/api/settings')
]);
return { user, stats, settings };
},
{
pick: ['user.id', 'user.name', 'stats.totalVisits']
// кэшируется только выбранные поля
}
);
Сравнение с React (SWR / React Query)
В React аналогичный функционал:
// React Query (современный стандарт)
import { useQuery } from '@tanstack/react-query';
const { data, isLoading, refetch } = useQuery({
queryKey: ['user', userId], // ключ кэша
queryFn: () => fetch(`/api/users/${userId}`).then(r => r.json()),
staleTime: 5 * 60 * 1000 // кэш свеж 5 минут
});
// SWR
import useSWR from 'swr';
const { data, error, mutate } = useSWR(
userId ? `/api/users/${userId}` : null, // ключ кэша
fetcher
);
Best Practices
1. Ключи должны быть уникальны и описательны
✓ useAsyncData('user-profile-123', ...)
✓ useAsyncData('products-category-electronics', ...)
✗ useAsyncData('data', ...) // слишком общий
✗ useAsyncData(`${Math.random()}`, ...) // не консистентный
2. Включай переменные в ключ кэша
const userId = route.params.id;
✓ useAsyncData(`user-${userId}`, () => fetchUser(userId))
✗ useAsyncData('user', () => fetchUser(userId)) // ключ не меняется
3. Используй watch для реактивности
const filter = ref('all');
✓ useAsyncData(
() => `products-${filter.value}`,
() => fetchProducts(filter.value),
{ watch: [filter] }
)
✗ useAsyncData(
'products',
() => fetchProducts(filter.value)
// filter меняется, но кэш не обновляется
)
4. Инвалидируй кэш после мутаций
const { refresh } = await useAsyncData('user', fetchUser);
const updateUser = async (data) => {
await postUpdate(data);
await refresh(); // обновить кэш
};
5. Используй pick для оптимизации payload
// Кэшируется полный ответ API (может быть большим)
✗ useAsyncData('user', () => $fetch('/api/user'))
// Кэшируются только нужные поля
✓ useAsyncData(
'user',
() => $fetch('/api/user'),
{ pick: ['id', 'name', 'email'] }
)
Итог
Кэширование в useAsyncData:
- Ключ кэша — обязательный, уникальный идентификатор
- Динамические ключи — включай переменные для разных данных
- watch — пересчитывать при изменении зависимостей
- refresh() — инвалидировать и пересчитать кэш
- pick — оптимизировать размер payload на сервере
- SSR — данные кэшируются на сервере и переиспользуются на клиенте
Это мощный инструмент для оптимизации производительности Nuxt приложений!