JS Advanced

Промисификация

Научиться оборачивать callback-based API в Promises, понять, когда promisification нужна, и почему в modern code она встречается реже.

Продвинутый (Advanced)

Кратко

Промисификация — превращение callback-based функции в функцию, возвращающую Promise. Нужна при работе со старыми API (Node.js callbacks). В modern code (fetch, async/await) promisification встречается реже.


Подробно

Проблема: callback-based API

function loadData(url, onSuccess, onError) { // ... }

loadData(url, (data) => console.log(data), (error) => console.log(error) );

Решение: promisification

function loadDataAsync(url) { return new Promise((resolve, reject) => { loadData(url, resolve, reject); }); }

// Теперь: const data = await loadDataAsync(url);

Утилита promisify: function promisify(fn) { return function(...args) { return new Promise((resolve, reject) => { fn(...args, (error, result) => { if (error) reject(error); else resolve(result); }); }); }; }

// Использование: const loadDataP = promisify(loadData); const data = await loadDataP(url);

Node.js: const { promisify } = require('util'); const readFile = promisify(require('fs').readFile); const content = await readFile('file.txt', 'utf8');

Когда НЕ нужна:

  • fetch() уже возвращает Promise
  • async/await уже работают с Promises
  • Современные API уже Promise-based

Ментальная модель

Промисификация — как переводчик с «callback-языка» на «Promise-язык». Старые API говорят на callback-языке («позвони мне, когда будет готово»). Промисификация переводит это на Promise-язык («жди результата»).


Примеры

**Самый простой:**

javascript
// Callback-based
function loadScript(src, callback) {
  const script = document.createElement('script');
  script.src = src;
  script.onload = () => callback(null, script);
  script.onerror = () => callback(new Error(`Failed: ${src}`));
  document.head.append(script);
}

// Promisified
function loadScriptAsync(src) {
  return new Promise((resolve, reject) => {
    loadScript(src, (error, script) => {
      if (error) reject(error);
      else resolve(script);
    });
  });
}

await loadScriptAsync('/app.js');

Промисификация callback-based loadScript.

**Простой:**

javascript
// Утилита promisify
function promisify(fn) {
  return (...args) => new Promise((resolve, reject) => {
    fn(...args, (err, result) => {
      err ? reject(err) : resolve(result);
    });
  });
}

// Пример использования
function slowOperation(data, callback) {
  setTimeout(() => callback(null, `Result: ${data}`), 1000);
}

const fast = promisify(slowOperation);
const result = await fast('test'); // 'Result: test'

Универсальная утилита для промисификации.

**Реальный пример:**

javascript
// Node.js: промисификация fs
const fs = require('fs');
const { promisify } = require('util');

const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile);

async function processFile(path) {
  const content = await readFile(path, 'utf8');
  const processed = content.toUpperCase();
  await writeFile(path, processed);
  console.log('Done!');
}

Node.js: промисификация встроенных модулей.


Частые ошибки

**Неправильно:** Промисифицировать modern API

**Почему:** fetch, async/await, современные Node.js API уже возвращают Promises.

**Правильно:** Промисификация нужна только для callback-based legacy API.

**Неправильно:** Забывать обработать ошибки в promisify

**Почему:** Если callback не вызывается — Promise «зависает» навсегда.

**Правильно:** Убедитесь, что callback всегда вызывается (resolve или reject).


Важно запомнить

  • Промисификация = callback → Promise
  • Нужна для legacy callback-based API
  • В modern code встречается реже
  • Node.js: util.promisify
  • Всегда обрабатывайте ошибки

Связь

Назад: Вы знаете Promise (JA4) и async/await (JA5). Промисификация соединяет старые API на колбэках с этим миром.

Вперёд: Следующий урок (JV11) — микрозадачи — порядок выполнения колбэков Promise.

Материалы курса JS Advanced — PROlab Academy.