Ответ
В 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.
Ответ 18+ 🔞
А, ну вот, опять про эту асинхронность в Node.js. Слушай, тут история, как с выбором между поехать на метро, на такси или пешком с бутылкой пива — все способы довезут, но ощущения, бля, пиздец какие разные.
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);
});
// А этот код-то выполнится ДО того, как файл прочитают, имей в виду
Проблема в чём? Да в том, что если тебе нужно после файла базу запросить, а потом ещё API дернуть, то получается этажерка из колбэков, или, как его называют, «ад колбэков». Читать это — волнение ебать, терпения ноль ебать. Чистая пиздопроебибна.
2. Промисы (Promises)
Тут уже поумнее. Это как дать тебе бумажку с обещанием, что результат будет. Многие модули сейчас уже отдают промисы (взять тот же fs.promises).
const fs = require('fs').promises;
fs.readFile('/path/to/file.txt', 'utf8')
.then((data) => {
console.log('Содержимое файла:', data);
})
.catch((err) => {
console.error('Ошибка чтения файла:', err);
});
Уже лучше, да? Можно цепочки строить, ошибки в одном месте ловить. Но всё равно, когда этих .then() овердохуища, тоже не сахар.
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);
// И вот тут уже спокойно дальше работай, как будто всё синхронно
} 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()
]);
// И всё, чувак, все результаты у тебя разом, красота!
}
Если честно, в современных проектах я давно уже на async/await пересел. Читаемость — огонь, ошибки через try/catch ловятся — как родные. В общем, ебать мои старые костыли, но это самый адекватный вариант.