Devs Hive
Повернутися до всіх запитань

Що таке Promisification?

JuniorJavaScript
Зустрічали на інтервʼю:1 користувач

На дворі вже 2026 рік, але це запитання про промісифікацію і досі гуляє по різних співбесідах, здебільшого на Junior-інтервʼю. Щоб зрозуміти, як працює даний костиль, потрібно розібрати проблематику.

Callback hell

Це ситуація, коли через багато асинхронних викликів на колбеках код перетворюється на піраміду з вкладених функцій. Через це його важко читати, дебажити і нормально обробляти помилки.

В Node.js callbacks будуються наступним чином - першим аргументом приходить помилка або null, якщо її немає. А другим аргументом приходять дані і типовий метод, який використовує callback, виглядає наступним чином:

getUser(userId, (err, user) => {
if (err) return handle(err);
// Якщо err=null, значить все окей і ми отримаємо user
console.log(user)
})

Якщо взяти цю функцію окремо, вона виглядає адекватно. Але як тільки наблизимося до реального проєкту, де може бути багато взаємозалежних викликів, починається callback hell.

getUser(userId, (err, user) => {
if (err) return handle(err);

getOrders(user.id, (err, orders) => {
if (err) return handle(err);

getOrderDetails(orders[0].id, (err, details) => {
if (err) return handle(err);

saveReport(details, (err) => {
if (err) return handle(err);

console.log("Готово!");
});
});
});
});

Тут приходить на допомогу промісифікація

Promisification - це коли callback-based функція огортається в Promise. Тоді замість вкладених колбеків можна зручно писати .then/.catch або async/await. Зазвичай ця техніка застосовується в двох випадках:

Коли Node.js тільки зарелізив Promise - звісно, після релізу не всі бібліотеки швидко змінили своє API з callback-based до Promise, тому доводилося огортати їх таким способом, щоб було зручніше працювати.

Legacy - зараз це найчастіше використовується для обгортання різного legacy. Наприклад, в системі є метод, який писався вашим прадідом, який звичайно використовував callback-based підхід.

Це метод має 2000 рядків коду, і переписувати його ніхто не буде, а от промісифікувати, щоб уникнути колбеків, цілком можна. І дуже часто це була частина рефакторингу, так як працювати з Promise набагато простіше і приємніше. Повернемося до методу getUser, який ми розглядали на початку. Ми можемо дуже швидко зробити з нього Promise.

const getUserAsync = (userId) => {
return new Promise((resolve, reject) => {
getUser(userId, (err, user) => {
if (err) return reject(err);
resolve(user);
});
});
}

// Далі ми можемо працювати з ним як з звичайним Promise
try {
const user = await getUserAsync(userId);
console.log(user);
} catch (err) {
handle(err);
}

А тепер подивимось, як буде виглядати callback hell, якщо його промісифікувати:

try {
const user = await getUserAsync(userId);

const orders = await getOrdersAsync(user.id);
if (!orders?.length) throw new Error("Немає замовлень");

const details = await getOrderDetailsAsync(orders[0].id);

await saveReportAsync(details);

console.log("Готово!");
} catch (err) {
handle(err);
}

Зустрічав на інтервʼю?

Коментарі (0)

Увійдіть, щоб залишити коментар

Поки що немає коментарів. Будьте першим!