Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Promise в JavaScript/Node.js
Promise — это объект в JavaScript, который представляет результат асинхронной операции (может быть успешно выполнена или отклонена). Это фундамент асинхронного программирования в современном Node.js.
Определение
Promise — это объект, который содержит:
- Состояние (state): pending, fulfilled (успех) или rejected (ошибка)
- Значение (value): результат успешной операции или причина ошибки
- Методы: then(), catch(), finally()
Жизненный цикл Promise
// Состояние: PENDING (ожидание)
const promise = new Promise((resolve, reject) => {
// resolve() или reject() изменит состояние
});
// После вызова resolve() → FULFILLED (выполнено)
// После вызова reject() → REJECTED (отклонено)
// Состояние не может измениться обратно!
Базовый синтаксис
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
const success = true;
if (success) {
resolve('Operation successful!'); // FULFILLED
} else {
reject('Operation failed!'); // REJECTED
}
}, 1000);
});
// Обработка результата
myPromise
.then((result) => {
console.log('Success:', result);
})
.catch((error) => {
console.error('Error:', error);
})
.finally(() => {
console.log('Cleanup');
});
then() — обработка успеха
const promise = Promise.resolve(5);
promise
.then((value) => {
console.log(value); // 5
return value * 2; // Возвращаем новое значение
})
.then((value) => {
console.log(value); // 10
});
// Цепочка then() создаёт новый Promise
catch() — обработка ошибок
const failedPromise = Promise.reject(new Error('Something went wrong'));
failedPromise
.catch((error) => {
console.error('Caught error:', error.message);
// Если здесь return значение → следующий then получит его
return 'recovered';
})
.then((value) => {
console.log(value); // 'recovered'
});
// catch() можно использовать вместо then(null, errorHandler)
finally() — очистка ресурсов
const promise = fetchData();
promise
.then((data) => console.log('Data:', data))
.catch((error) => console.error('Error:', error))
.finally(() => {
// Выполнится в ЛЮБОМ случае (успех или ошибка)
console.log('Closing connection...');
});
Статические методы Promise
Promise.resolve() — создать успешный Promise
const promise = Promise.resolve('Hello');
// То же самое что:
// new Promise((resolve) => resolve('Hello'));
promise.then((value) => console.log(value)); // Hello
Promise.reject() — создать отклонённый Promise
const promise = Promise.reject(new Error('Failed'));
// То же самое что:
// new Promise((resolve, reject) => reject(new Error('Failed')));
promise.catch((error) => console.error(error)); // Error: Failed
Promise.all() — ждать все Promise
const promise1 = fetch('/api/users');
const promise2 = fetch('/api/posts');
const promise3 = fetch('/api/comments');
Promise.all([promise1, promise2, promise3])
.then(([users, posts, comments]) => {
console.log('All done:', { users, posts, comments });
})
.catch((error) => {
// Если ЛЮБОЙ Promise rejected → сразу в catch
console.error('One failed:', error);
});
Promise.race() — первый результат
const timeout = new Promise((_, reject) =>
setTimeout(() => reject('Timeout'), 5000)
);
const request = fetch('/api/slow-endpoint');
Promise.race([request, timeout])
.then((data) => console.log('Success:', data))
.catch((error) => console.error('Timeout or error:', error));
Promise.allSettled() — все результаты
const promises = [
Promise.resolve(1),
Promise.reject(new Error('Failed')),
Promise.resolve(3),
];
Promise.allSettled(promises)
.then((results) => {
console.log(results);
// [
// { status: 'fulfilled', value: 1 },
// { status: 'rejected', reason: Error },
// { status: 'fulfilled', value: 3 },
// ]
});
Async/Await — синтаксический сахар для Promise
Async/Await делает код с Promise более читаемым, как синхронный:
// Без async/await (с Promise)
function getUser(id) {
return fetch(`/api/users/${id}`)
.then((res) => res.json())
.then((user) => {
if (user.id === 1) {
return fetch(`/api/users/${id}/profile`);
}
return user;
})
.then((data) => data.json())
.catch((error) => console.error('Error:', error));
}
// С async/await (более читаемо!)
async function getUser(id) {
try {
const res = await fetch(`/api/users/${id}`);
let user = await res.json();
if (user.id === 1) {
const profileRes = await fetch(`/api/users/${id}/profile`);
user = await profileRes.json();
}
return user;
} catch (error) {
console.error('Error:', error);
throw error;
}
}
Реальный пример: Node.js API
// Без обработки Promise правильно
app.get('/users/:id', (req, res) => {
const user = getUserFromDB(req.params.id); // Возвращает Promise!
res.json(user); // Ошибка! user — это Promise, не объект
});
// Правильно с async/await
app.get('/users/:id', async (req, res) => {
try {
const user = await getUserFromDB(req.params.id);
res.json(user);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// Или с .then().catch()
app.get('/users/:id', (req, res) => {
getUserFromDB(req.params.id)
.then((user) => res.json(user))
.catch((error) => res.status(500).json({ error: error.message }));
});
Типичные ошибки с Promise
Ошибка 1: Забыть return в цепочке then()
// Плохо
promise
.then((value) => {
const result = value * 2; // return забыли!
})
.then((result) => {
console.log(result); // undefined!
});
// Хорошо
promise
.then((value) => {
return value * 2; // или просто: const result = value * 2; return result;
})
.then((result) => {
console.log(result); // Правильное значение
});
Ошибка 2: Забыть catch() на конце цепочки
// Плохо — необработанное отклонение
promise
.then((value) => {
throw new Error('Oops');
})
.then((value) => {
console.log(value);
});
// Ошибка будет проигнорирована!
// Хорошо
promise
.then((value) => {
throw new Error('Oops');
})
.then((value) => {
console.log(value);
})
.catch((error) => {
console.error('Handled:', error);
});
Ошибка 3: Создать Promise hell (Callback hell для Promise)
// Плохо — вложенные then
getUser(1)
.then((user) => {
getProfile(user.id).then((profile) => {
getPosts(user.id).then((posts) => {
console.log(user, profile, posts);
});
});
});
// Хорошо — цепочка then
getUser(1)
.then((user) => getProfile(user.id).then((profile) => ({ user, profile })))
.then(({ user, profile }) => getPosts(user.id).then((posts) => ({ user, profile, posts })))
.then(({ user, profile, posts }) => console.log(user, profile, posts));
// Или ещё лучше — async/await
async function getFullUserData(id) {
const user = await getUser(id);
const profile = await getProfile(user.id);
const posts = await getPosts(user.id);
return { user, profile, posts };
}
Promise vs Callback vs Async/Await
Callback (старый подход, избегать):
function getUser(id, callback) {
setTimeout(() => {
callback(null, { id, name: 'John' });
}, 1000);
}
getUser(1, (error, user) => {
if (error) console.error(error);
else console.log(user);
});
Promise (современный подход):
function getUser(id) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve({ id, name: 'John' });
}, 1000);
});
}
getUser(1).then((user) => console.log(user));
Async/Await (лучший подход):
async function getUser(id) {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ id, name: 'John' });
}, 1000);
});
}
const user = await getUser(1);
console.log(user);
Почему Promise важен
- Асинхронность — операции не блокируют основной поток
- Обработка ошибок — через catch() вместо try/catch
- Цепочки операций — связывать асинхронные операции
- Composability — Promise.all(), Promise.race() и т.д.
- Основа для async/await — современный способ писать асинхронный код