async / await
Урок: async / await
Введение
Когда мы разобрались с Promise, стало понятно, что они помогают работать с асинхронным кодом. Но при этом у них есть проблема: цепочки then могут становиться длинными и сложными для чтения.
Представь, что тебе нужно выполнить несколько действий подряд: сначала загрузить пользователя, потом получить его заказы, потом обработать их. С then это превращается в цепочку, где легко запутаться.
В реальной жизни мы думаем по-другому: «сначала сделай это, потом это, потом это». То есть последовательно.
Именно такую возможность даёт async / await.
Он позволяет писать асинхронный код так, как будто он синхронный — проще, понятнее и ближе к обычному мышлению.
Что такое async
Ключевое слово async используется для объявления асинхронной функции.
Чтобы увидеть результат в консоли, объявление и потребление Promise объединим в один фрагмент:
async function sayHello() {
return 'Привет';
}
sayHello().then((result) => {
console.log(result);
});
Результат:
Привет
Даже если ты просто возвращаешь строку, JavaScript автоматически «оборачивает» её в Promise.
Это значит: async превращает функцию в асинхронную.
Что такое await
Ключевое слово await используется внутри async функции.
Оно «останавливает» выполнение функции до тех пор, пока Promise не завершится.
Пример:
function getData() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('Данные получены');
}, 1000);
});
}
async function main() {
let result = await getData();
console.log(result);
}
main();
Результат через ~1 секунду:
Данные получены
Разберём:
getData()возвращает Promise;awaitждёт его выполнения;- результат записывается в
result; - дальше код продолжается.
Как это выглядит по сравнению с then
Посмотрим два варианта на мгновенно выполняющемся Promise (без долгой задержки), чтобы в песочнице быстрее увидеть вывод.
Через then:
function getData() {
return Promise.resolve('Данные получены');
}
getData().then((result) => {
console.log(result);
});
Через async/await:
function getData() {
return Promise.resolve('Данные получены');
}
async function main() {
let result = await getData();
console.log(result);
}
main();
Второй вариант читается проще — как обычный последовательный код.
Несколько асинхронных операций подряд
Одна из главных причин использовать async / await — это работа с несколькими операциями.
function step1() {
return Promise.resolve('Шаг 1');
}
function step2() {
return Promise.resolve('Шаг 2');
}
async function process() {
let result1 = await step1();
console.log(result1);
let result2 = await step2();
console.log(result2);
}
process();
Результат:
Шаг 1
Шаг 2
Здесь код читается сверху вниз, как обычная последовательность действий.
Обработка ошибок через try/catch
С Promise ошибки обрабатываются через catch.
С async / await используется обычный try/catch.
function getData() {
return new Promise((resolve, reject) => {
reject('Ошибка!');
});
}
async function main() {
try {
let result = await getData();
console.log(result);
} catch (error) {
console.log(error);
}
}
main();
Результат:
Ошибка!
Это делает код более привычным, особенно если ты уже знаком с синхронными ошибками.
Важные ограничения
await можно использовать только внутри async функций (или в модулях с поддержкой top-level await).
Нельзя написать «голый» await в обычном скрипте вне async — будет синтаксическая ошибка. Правильный шаблон — обернуть ожидание в async-функцию и вызвать её:
function getData() {
return Promise.resolve('ok');
}
async function main() {
let result = await getData();
console.log(result);
}
main();
Это одно из ключевых правил.
Что происходит на самом деле
Хотя await выглядит как «ожидание», JavaScript не блокирует выполнение всей программы.
Он:
- «ставит на паузу» только текущую функцию;
- остальной код продолжает выполняться;
- когда Promise завершается — функция продолжает работу.
Это важно: await не делает код синхронным, он просто делает его более читаемым.
Где это используется на практике
async / await используется почти везде:
- запросы к серверу (
fetch); - работа с API;
- загрузка данных;
- обработка форм;
- взаимодействие с базами данных.
Например, два последовательных «шага» без реальной сети (имитация fetch + json()):
async function loadUser() {
let response = await Promise.resolve({
json: async () => ({ name: 'Stepan', role: 'student' }),
});
let data = await response.json();
console.log(data);
}
loadUser();
Здесь:
- сначала ждём «ответ» (здесь это уже готовый объект);
- затем ждём
json()(тоже Promise); - затем используем данные.
В реальном коде вместо Promise.resolve({...}) будет await fetch(url).
Итоговое понимание
async / await — это способ работать с асинхронным кодом так, как будто он синхронный.
async делает функцию асинхронной и возвращающей Promise.
await позволяет дождаться результата и работать с ним как с обычным значением.
Ключевая идея в том, что async / await упрощает чтение и написание кода. Он не меняет саму асинхронность, а делает её более понятной.
Если Promise — это инструмент, то async / await — это удобный способ им пользоваться.