Промисы: блок await
Данные с сервера приходят не сразу: запрос возвращает промис, который выполнится позже. Блок {#await} позволяет описать в разметке все три состояния промиса — ожидание, успех и ошибку — без лишних переменных вроде isLoading.
Три ветки
Для примера возьмём тестовый сервис jsonplaceholder.typicode.com, который отдаёт задачи в формате JSON:
<!-- src/routes/+page.svelte -->
<script>
async function loadTodos() {
const response = await fetch('https://jsonplaceholder.typicode.com/todos?_limit=5');
if (!response.ok) throw new Error('Сервер ответил ошибкой');
return response.json();
}
let promise = $state(loadTodos());
</script>
{#await promise}
<p>Загрузка...</p>
{:then todos}
<ul>
{#each todos as todo (todo.id)}
<li>{todo.title}</li>
{/each}
</ul>
{:catch error}
<p>Не удалось загрузить: {error.message}</p>
{/await}Сначала на странице мелькнёт «Загрузка...», затем появится список из пяти задач. Если отключить интернет и обновить страницу, вы увидите сообщение об ошибке. Значение в ветке {:then todos} — результат промиса, в {:catch error} — причина отказа.
Повторный запрос
Блок следит за переменной с промисом. Присвойте ей новый промис — и блок снова пройдёт путь от загрузки к результату:
<!-- src/routes/+page.svelte: добавьте кнопку под блоком await -->
<button onclick={() => (promise = loadTodos())}>Обновить</button>После клика опять появится «Загрузка...», а затем свежий список. Поэтому промис хранят в $state: обычная переменная не сообщила бы блоку о замене.
Короткие формы
Если индикатор загрузки не нужен, ветку then пишут прямо в открывающем теге:
<script>
let promise = $state(fetch('https://jsonplaceholder.typicode.com/todos/1').then((r) => r.json()));
</script>
{#await promise then todo}
<p>Первая задача: {todo.title}</p>
{/await}Пока промис не выполнен, на этом месте ничего нет. Ошибки в такой записи не показываются — добавьте , если они важны.
Где загружать данные в SvelteKit
Блок {#await} хорош для запросов по действию пользователя: поиск, кнопка «Обновить». Данные, нужные странице сразу при открытии, в SvelteKit обычно получают функцией load — о ней отдельный урок в главе SvelteKit.
Частая ошибка
Вызывать функцию загрузки прямо в разметке:
<script>
async function loadTodos() {
const response = await fetch('https://jsonplaceholder.typicode.com/todos?_limit=5');
return response.json();
}
</script>
{#await loadTodos() then todos}
<p>Задач: {todos.length}</p>
{/await}Такой код работает, но запрос нельзя повторить, а при каждом пересоздании блока он отправится заново. Сохраняйте промис в переменную и передавайте в {#await} её.