Что такое контракт thennable

Ответ

Объект является thenable (или "then-able"), если он имеет метод then(), что делает его совместимым с промисами. Это используется для асинхронных операций, где объект может быть обработан как промис, даже если он им не является.

Пример:

const thenable = {
  then(resolve, reject) {
    setTimeout(() => resolve('Done!'), 1000);
  }
};

Promise.resolve(thenable).then(console.log); // 'Done!' через 1 сек

Особенности:

  • Используется для интеграции с Promise API
  • Может быть как объектом, так и экземпляром класса
  • Позволяет создавать свои асинхронные абстракции
  • Важно для работы с async/await, так как они работают с thenable

Ответ 18+ 🔞

А, слушай, вот эта штука — thenable, ну или «тенейбл», если по-буржуйски. По сути, это просто объект, у которого есть метод then(). И всё, блядь! Не обязательно быть полноценным промисом, достаточно притвориться. Система смотрит: «О, у тебя есть then? Ну окей, значит ты свой, асинхронный братан, проходи».

Зачем это надо? Ну, например, когда ты какой-нибудь левый объект из старой библиотеки суёшь в Promise.resolve(), а он, зараза, не промис, но у него then есть — и всё, система его принимает как родного. Хитрая жопа, да?

Вот смотри, как это выглядит в коде, тут всё просто:

const thenable = {
  then(resolve, reject) {
    setTimeout(() => resolve('Done!'), 1000);
  }
};

Promise.resolve(thenable).then(console.log); // 'Done!' через 1 сек

Видишь? Объект thenable — он не промис, ёпта! У него нет всех этих catch, finally, но есть метод then. И когда ты его засовываешь в Promise.resolve(), движок такой: «Ага, уважаю, у тебя договор подписан — метод then на месте. Значит, будем ждать, пока твой resolve или reject выстрелят».

И это, блядь, очень важно для async/await, потому что эта парочка тоже работает через thenable. Если твой объект умеет в then, его можно await-ить, как будто так и надо. Вообще, иногда кажется, что это какая-то магия, но на самом деле — просто договорённость, контракт, понимаешь? «У тебя есть then — ты в теме, нет — иди нахуй, в синхронном мире живи».

Так что, если вдруг захочешь свою асинхронную абстракцию наколхозить — просто сделай объект с методом then, и все промисовые штуки начнут с ним работать. Главное — не облажайся и правильно resolve или reject вызывай, а то потом будешь сидеть и думать: «Почему это всё зависло, блядь?».