Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Промисы: блок 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} её.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.