
Сетевой запрос — это несколько возможных состояний, а не только await fetch. Страница должна отличать ожидание, пустой ответ, ошибку и готовые данные. Сделаем локальный список с повторной попыткой: кнопка блокируется на время запроса, а исключение не оставляет интерфейс в вечной загрузке.
Два файла для загрузки списка с повтором
index.html
<!doctype html>
<html lang="ru"><meta charset="utf-8"><title>Загрузка списка</title>
<button id="load" type="button">Загрузить или повторить</button>
<p id="state" aria-live="polite">Данные ещё не загружены</p><ul id="items"></ul>
<script>
const button = document.querySelector('#load');
const state = document.querySelector('#state');
const list = document.querySelector('#items');
async function loadItems(fetcher = fetch) {
const response = await fetcher('./items.json');
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
if (!Array.isArray(data) || !data.every(x => typeof x === 'string')) {
throw new TypeError('Ожидается массив строк');
}
return data;
}
button.addEventListener('click', async () => {
button.disabled = true;
state.textContent = 'Загрузка…';
list.replaceChildren();
try {
const data = await loadItems();
list.replaceChildren(...data.map(text => {
const li = document.createElement('li'); li.textContent = text; return li;
}));
state.textContent = data.length ? `Получено: ${data.length}` : 'Список пуст';
} catch { state.textContent = 'Не удалось загрузить список. Можно повторить.'; }
finally { button.disabled = false; }
});
</script></html>
items.json
["Разминка", "Основная часть", "Заминка"]
Сохраните оба файла рядом и запустите python -m http.server 8000 из этой папки. Откройте http://localhost:8000. Для проверки 404 временно переименуйте только учебный items.json, затем верните и повторите запрос. Не выполняйте такой тест на рабочем источнике данных.
| Что сравнить | На что смотреть | Что сделать |
|---|---|---|
| Ожидание | Кнопка недоступна | Нет повторных параллельных запросов |
| HTTP-ошибка | Ответ получен, но ok равен false | Показать понятную ошибку |
| Неверный формат | JSON не соответствует контракту | Не строить интерфейс из случайного объекта |
| Пустой массив | Корректный ответ без элементов | Показать отдельное пустое состояние |
Почему try недостаточно без проверки ok
MDN поясняет, что HTTP-ответ 404 сам по себе не отклоняет promise fetch. Поэтому статус проверяется явно. Затем отдельно может завершиться ошибкой чтение JSON. Проверка структуры нужна уже после синтаксического разбора: корректный JSON ещё не означает массив строк.
- Проверить успешную загрузку и пустой массив.
- Проверить HTTP-ошибку.
- Проверить повреждённый JSON и объект вместо массива.
- Убедиться, что после ошибки кнопка снова доступна.
Вопросы и ответы
Нужен ли no-cors при ошибке?
Нет. Он не является универсальным исправлением и может сделать ответ недоступным для чтения. Разбирайте причину и серверные условия.
Почему очищается прежний список?
Это выбранное поведение примера. В другом продукте можно сохранять старые данные с явной отметкой об их состоянии.
Где журналировать техническую причину?
В подходящей системе диагностики без лишних персональных данных. Пользовательское сообщение и технический лог имеют разные задачи.
Повтор безопасен для любого запроса?
Нет. Здесь только чтение локального файла. Для операций изменения данных нужна отдельная защита от повторов.
Источники: developer.mozilla.org.




