Промисы и async/await
Асинхронность без ада колбэков
Зачем это нужно
Запрос к серверу занимает время. Если ждать его синхронно, страница замёрзнет. Поэтому JavaScript не ждёт: он получает промис — обещание вернуть результат позже.
Promise в трёх состояниях
Промис либо ждёт (pending), либо выполнен (fulfilled), либо отклонён (rejected). Обработка — через then и catch:
fetch("/api/posts")
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err));
async/await — тот же промис, читается проще
async function load() {
try {
const res = await fetch("/api/posts");
if (!res.ok) throw new Error(res.status);
return await res.json();
} catch (e) {
console.error("Не загрузилось", e);
}
}
await приостанавливает только текущую функцию, а не страницу. async гарантирует, что функция вернёт промис — даже если внутри обычный return.
fetch не падает на 404
Это самая частая ловушка. fetch отклоняет промис только при сетевой ошибке. Ответ 404 или 500 — это успешно полученный ответ, и catch не сработает. Проверяйте res.ok вручную.
Параллельные запросы
Последовательные await складывают время: два запроса по секунде дадут две секунды. Если они независимы — запускайте вместе:
const [user, posts] = await Promise.all([
fetch("/api/user").then(r => r.json()),
fetch("/api/posts").then(r => r.json())
]);
Promise.all падает, если хотя бы один запрос не удался. Promise.allSettled дождётся всех и вернёт статусы — удобно, когда часть данных не критична.
Типичные ошибки
- Забытый await. Получаете промис вместо данных и печатаете
[object Promise]. - await в forEach. Колбэк не ждётся; для последовательности нужен
for...of. - Нет обработки ошибок. Необработанный reject валит консоль и оставляет интерфейс пустым.
- Запрос без отмены. Пользователь ушёл со страницы, а ответ пришёл — нужен
AbortController.
Нужен сайт, а не статья?
Напишу фронтенд без лишних зависимостей: интерактив, формы, запросы к API. С 2009 года, по договору, с поддержкой после запуска.
Полезно по теме: JavaScript с нуля, DOM и события, хуки React.