Node.js async/await
В Node.js,async/awaitявляется синтаксическим сахаром для обработки асинхронных операций.
async/awaitОн основан на Promise, но заставляет асинхронный код выглядеть более похожим на синхронный код, значительно улучшая читаемость и сопровождаемость кода.
asyncключевое слово используется для объявления функции как асинхронной, иawaitключевое слово используется для ожидания разрешения или отклонения Promise.
Использованиеasync/awaitпозволяет избежать ада обратных вызовов и сделать обработку ошибок более интуитивной.

JavaScript является однопоточным. При встрече с асинхронными задачами (такими как setTimeout или сетевые запросы) он передаёт их API браузера, а по завершении помещает обратный вызов в очередь сообщений.
Цикл событий постоянно проверяет, пуст ли стек вызовов. Если он пуст, он берёт обратный вызов из очереди и помещает его в стек вызовов для выполнения. Это предотвращает блокировку главного потока при обработке асинхронных результатов по порядку.
Базовый синтаксис
асинхронные функции
Любую функцию можно сделать асинхронной, добавивasyncключевое слово:
return "Hello World";
}
asyncАсинхронная функция всегда возвращает Promise. Если возвращаемое значение не является Promise, оно автоматически оборачивается в Promise.
await-выражения
awaitможно использовать толькоasyncвнутри асинхронной функции. Он приостанавливает выполнение функции, ждёт разрешения Promise, затем продолжает выполнение и возвращает результат:
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
}
Обработка ошибок
подход try/catch
Обработкаasync/awaitНаиболее распространённый способ обработки ошибок — использоватьtry/catch:
Пример
try {
const response = await fetch('https://api.example.com/user');
const user = await response.json();
return user;
} catch (error) {
console.error('Error fetching user:', error);
throw error; // При необходимости повторно выбросить ошибку
}
}
Обработка Promise напрямую
Вы также можете напрямую обработать возвращённый Promise:
Пример
.then(user => console.log(user))
.catch(error => console.error(error));
Практические примеры
Выполнение нескольких асинхронных операций параллельно
ИспользуйтеPromise.allwithasync/awaitчтобы выполнять несколько асинхронных операций параллельно:
Пример
try {
const requests = urls.map(url => fetch(url));
const responses = await Promise.all(requests);
const data = await Promise.all(responses.map(r => r.json()));
return data;
} catch (error) {
console.error('Ошибка при получении данных:', error);
throw error;
}
}
Пример операции с базой данных
Пример
try {
const user = await User.findById(userId);
const posts = await Post.find({ userId });
return { user, posts };
} catch (error) {
console.error('Database error:', error);
throw error;
}
}
Лучшие практики
- Всегда обрабатывайте ошибки: Не игнорируйте
awaitошибки, которые могут быть выброшены; используйтеtry/catchили.catch()для обработки - Избегайте ненужного await: Если вам не нужно ждать результата, вы можете вернуть Promise напрямую
- Используйте параллелизм разумно: Несколько независимых асинхронных операций должны выполняться параллельно (используйте
Promise.all) - Поддерживайте код понятным: Избегайте чрезмерно глубокой
async/awaitвложенности; выделяйте функции при необходимости - Следите за влиянием на производительность: Каждый
awaitприостанавливает выполнение функции; обращайте особое внимание в циклах
Часто задаваемые вопросы
Связь между async/await и Promise
async/await— это синтаксический сахар, построенный поверх Promise. Любаяasync-функция возвращает Promise, и любойawaitможет стоять перед Promise.
Почему моя async-функция возвращает undefined?
Возможно, это потому, что вы забыли использоватьawaitbeforereturn, или функция завершается до того, как Promise разрешится.
Можно ли использовать await на верхнем уровне?
В ES-модулях (файлах с расширением.mjsилиpackage.jsonСредняя"type": "module"), можно использоватьawaitнапрямую на верхнем уровне. В модулях CommonJS его нужно обернуть вasyncфункцию.
Пример
const data = await fetchData();
console.log(data);