В чем разница между аsync/await и рromise
async/await и Promise — это два взаимосвязанных механизма для работы с асинхронным кодом в JavaScript, но с разными уровнями абстракции и синтаксисом. Оба опираются на одно и то же основание — Promise, но async/await предоставляет более удобный, синхроноподобный способ записи асинхронного кода.
🔹 Что такое Promise
Promise — это объект, представляющий будущее завершение (или неудачу) асинхронной операции и её результат. Он может находиться в одном из трёх состояний:
-
Pending (ожидание) — операция ещё не завершена;
-
Fulfilled (успешно выполнено) — операция завершена успешно;
-
Rejected (отклонено) — операция завершена с ошибкой.
Создание и использование Promise:
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Результат");
// reject("Ошибка");
}, 1000);
});
promise
.then(result => console.log(result))
.catch(error => console.error(error));
Здесь then обрабатывает успешное завершение, catch — ошибку. Обработчики можно вызывать цепочкой: .then().then().catch()
🔹 Что такое async/await
async/await — это синтаксический сахар над Promise, который позволяет писать асинхронный код, выглядящий как синхронный. Это упрощает чтение и сопровождение кода, особенно при последовательных или вложенных асинхронных вызовах.
-
Ключевое слово async используется перед функцией — оно автоматически возвращает Promise.
-
Ключевое слово await используется для приостановки выполнения до завершения Promise.
Пример с async/await:
async function fetchData() {
try {
const result = await someAsyncOperation();
console.log(result);
} catch (error) {
console.error(error);
}
}
Это аналогично:
someAsyncOperation()
.then(result => console.log(result))
.catch(error => console.error(error));
🔸 Отличия между Promise и async/await
Категория | Promise | async/await |
---|---|---|
Основан на | Собственная реализация | Promise под капотом |
--- | --- | --- |
Синтаксис | Цепочки .then() и .catch() | Более линейный и читаемый синтаксис |
--- | --- | --- |
Обработка ошибок | Метод .catch() | Конструкция try...catch |
--- | --- | --- |
Уровень абстракции | Ближе к "ручному" управлению | Более высокоуровневый |
--- | --- | --- |
Удобство при множественных вызовах | Может быть сложно при глубокой вложенности | Проще писать цепочки, похожие на синхронный код |
--- | --- | --- |
Совместимость | Поддерживается с ES6 | Появился в ES2017 (ES8) |
--- | --- | --- |
Возвращаемое значение | Возвращает объект Promise | Также возвращает Promise |
--- | --- | --- |
Параллелизм | Можно реализовать с Promise.all() | Также можно с await Promise.all([...]) |
--- | --- | --- |
Отладка | Сложнее из-за цепочек | Проще: стек вызовов ближе к обычным функциям |
--- | --- | --- |
🔸 Пример сравнения
С использованием Promise:
function getUserData() {
return fetch("/user")
.then(res => res.json())
.then(user => {
return fetch(\`/user/${user.id}/posts\`)
.then(res => res.json());
})
.catch(error => console.error(error));
}
С использованием async/await:
async function getUserData() {
try {
const resUser = await fetch("/user");
const user = await resUser.json();
const resPosts = await fetch(\`/user/${user.id}/posts\`);
const posts = await resPosts.json();
return posts;
} catch (error) {
console.error(error);
}
}
🔸 Обработка нескольких асинхронных операций
- Параллельно:
// Promise:
Promise.all(\[fetch(url1), fetch(url2)\]).then((\[res1, res2\]) => {});
// async/await:
const \[res1, res2\] = await Promise.all(\[fetch(url1), fetch(url2)\]);
- Последовательно:
// async/await
const data1 = await fetch(url1);
const data2 = await fetch(url2); // ждет завершения первого
🔸 Ошибки и подводные камни
1. await работает только внутри async функции:
await somePromise(); // ❌ SyntaxError
2. async функция всегда возвращает Promise:
async function foo() {
return 42;
}
foo().then(console.log); // 42
3. Обработка ошибок в async/await требует try...catch:
try {
await failingPromise();
} catch (err) {
console.error("Ошибка:", err);
}
4. Последовательное выполнение может замедлить выполнение:
// ❌ так делать неэффективно, если вызовы независимы
const a = await fetchA();
const b = await fetchB();
Лучше:
// ✅ параллельно
const \[a, b\] = await Promise.all(\[fetchA(), fetchB()\]);
🔸 В каких случаях что использовать
-
Promise:
-
Подходит для базовых асинхронных операций;
-
Удобен при необходимости построения сложной цепочки, особенно с промежуточной логикой;
-
Используется в библиотеках, где необходимо программно комбинировать и управлять обещаниями.
-
-
async/await:
-
Предпочтительнее в прикладной логике и бизнес-коде;
-
Читаемее и удобнее для линейного кода;
-
Легче отлаживать и сопровождать.
-
Таким образом, async/await — это не альтернатива Promise, а более удобный способ их использования. Все асинхронные функции с async возвращают Promise, а await просто приостанавливает выполнение до его разрешения.