Ответ
В Node.js, где все I/O-операции асинхронны по умолчанию, есть три основных подхода для работы с асинхронным кодом.
1. Колбэки (Callbacks)
Исторически первый и до сих пор распространенный в базовом API Node.js (например, fs, http). Функция передается как аргумент и вызывается по завершении операции.
const fs = require('fs');
fs.readFile('/path/to/file.txt', 'utf8', (err, data) => {
if (err) {
console.error('Ошибка чтения файла:', err);
return;
}
console.log('Содержимое файла:', data);
});
// Код здесь выполнится ДО того, как файл будет прочитан
Главный недостаток — «ад колбэков» (callback hell) при вложенных асинхронных операциях.
2. Промисы (Promises)
Более современная абстракция, представляющая будущий результат. Многие нативные модули Node.js теперь предоставляют API, возвращающее промисы (например, fs.promises).
const fs = require('fs').promises;
fs.readFile('/path/to/file.txt', 'utf8')
.then((data) => {
console.log('Содержимое файла:', data);
})
.catch((err) => {
console.error('Ошибка чтения файла:', err);
});
Промисы позволяют организовывать цепочки вызовов (chaining) и удобно обрабатывать ошибки.
3. Async/Await Синтаксический сахар над промисами, позволяющий писать асинхронный код в стиле, похожем на синхронный.
const fs = require('fs').promises;
async function readAndProcessFile() {
try {
const data = await fs.readFile('/path/to/file.txt', 'utf8');
console.log('Содержимое файла:', data);
// Здесь можно продолжить работу с data
} catch (err) {
console.error('Ошибка чтения файла:', err);
}
}
readAndProcessFile();
Ключевые моменты:
awaitможно использовать только внутри функций, объявленных сasync.asyncфункция всегда возвращает Promise.- Для параллельного выполнения нескольких независимых операций используйте
Promise.all().async function fetchAllData() { const [userData, productList, config] = await Promise.all([ fetchUser(), fetchProducts(), loadConfig() ]); // Обработка всех результатов одновременно }На практике в современных проектах на Node.js я предпочитаю использовать
async/awaitза его читаемость и простоту обработки ошибок черезtry/catch.