Когда загрузка не удалась
Страница в этом упражнении пишет Загрузка… и больше ничего, сколько ни жди. Почему — сообщает консоль:
[Vue warn]: Unhandled error during execution of mounted hook
at <App>
SyntaxError: Failed to execute 'json' on 'Response': Unexpected token 'N', "Not Found" is not valid JSON
at eval (App.vue:9)В названии файла опечатка: menus.json. Такого файла нет, поэтому сервер отвечает статусом 404 Not Found, как вы знаете из курса по JavaScript, и вместо меню присылает текст Not Found. В строке 9 response.json() не может прочитать его как JSON и завершается ошибкой, а функция в onMounted на этом останавливается. До loading.value = false дело не доходит, поэтому страница продолжает писать Загрузка….
Проверяйте response.ok до чтения данных: оно равно false, когда сервер ответил ошибкой. Сообщение для посетителя храните в рефе, а loading сбрасывайте в false в обоих случаях:
const error = ref("");
onMounted(async () => {
const response = await fetch("menu.json");
if (!response.ok) {
error.value = "Не удалось загрузить меню.";
} else {
menu.value = await response.json();
}
loading.value = false;
});В шаблоне сообщение — третий вариант между двумя другими, он оформляется через v-else-if, знакомый вам по уроку «Условия и списки»:
<template>
<h1>Кафе «Уголок»</h1>
<p v-if="loading">Загрузка…</p>
<p v-else-if="error" class="error">{{ error }}</p>
<ul v-else>
<li v-for="item in menu" :key="item.id">{{ item.name }}: €{{ item.price }}</li>
</ul>
</template>Пустая строка в условии считается ложью, а любая другая — истиной, поэтому сообщение показывается, только когда оно есть.
А что, если соединения нет совсем? Тогда ответ не приходит, и сам fetch() завершается ошибкой TypeError: Failed to fetch, которую нужно перехватывать через try/catch, как в курсе по JavaScript. В предпросмотре ответ приходит всегда, поэтому здесь вы проверите response.ok.
Задание
- 1
Добавьте реф
errorс пустой строкой. ВonMountedпроверьтеresponse.ok: если оно равноfalse, запишите вerrorтекстНе удалось загрузить меню., иначе прочитайте меню. После обоих вариантов сделайтеloadingравнымfalse. Показывайте сообщение через<p v-else-if="error" class="error">между абзацем и списком. - 2
Теперь исправьте название файла в
fetch(), чтобы страница показала меню.