Загрузка данных
Задачи обычно хранятся на сервере, и компонент должен получить их после открытия страницы. Alpine понимает асинхронный код: метод init() может быть async, а внутри него работает await. Пока данные идут, пользователю показывают надпись «Загрузка…».
Заглушка вместо сервера
В примерах урока настоящий запрос заменён функцией, которая возвращает промис и отвечает через секунду, — как медленный сервер. В рабочем проекте на её месте будет fetch().
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<script>
function loadTasks() {
return new Promise(resolve => {
setTimeout(() => resolve(['Купить молоко', 'Позвонить Олегу']), 1000);
});
}
</script>
<ul x-data="{
tasks: [],
async init() {
this.tasks = await loadTasks();
}
}">
<template x-for="task in tasks">
<li x-text="task"></li>
</template>
</ul>Через секунду после открытия страницы появляются две задачи. Нажмите «Сбросить» в шапке результата, чтобы увидеть это снова.
Состояние загрузки
Свойство loading показывает, идёт ли запрос. Блок try...finally гарантирует, что оно сбросится в любом случае:
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<script>
function loadTasks() {
return new Promise(resolve => {
setTimeout(() => resolve(['Купить молоко', 'Позвонить Олегу']), 1000);
});
}
</script>
<div x-data="{
tasks: [],
loading: true,
async init() {
try {
this.tasks = await loadTasks();
} finally {
this.loading = false;
}
}
}">
<p x-show="loading">Загрузка…</p>
<ul x-show="!loading">
<template x-for="task in tasks">
<li x-text="task"></li>
</template>
</ul>
</div>Сначала видна надпись «Загрузка…», через секунду её сменяет список.
Ошибка
Запрос может не удаться. Ошибку ловят в catch и показывают сообщение:
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
<script>
function loadTasks() {
return new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('Сервер недоступен')), 1000);
});
}
</script>
<div x-data="{ tasks: [], error: '', async init() {
try {
this.tasks = await loadTasks();
} catch (e) {
this.error = e.message;
}
} }">
<p x-show="error" x-text="'Ошибка: ' + error"></p>
</div>Через секунду появляется «Ошибка: Сервер недоступен».
С настоящим сервером
В проекте функция загрузки обращается к API через fetch(), как в уроке «Запросы к серверу: fetch» учебника:
// src/api.js
export async function loadTasks() {
const response = await fetch('/api/tasks');
if (!response.ok) throw new Error('Ошибка ' + response.status);
return response.json();
}Компонент при этом не меняется: он так же ждёт промис через await.
Частая ошибка
Читать данные, которых ещё нет. Пока промис не выполнился, tasks пуст, а selected равен null. Выражение x-text="selected.title" упадёт с ошибкой до прихода ответа. Задавайте начальные значения в x-data — пустой массив, пустую строку — и прячьте зависимые блоки за x-if, пока данных нет.