0 added
0 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>Если в проекте появились промисы, то, по-хорошему, весь код должен работать только через них. К сожалению, далеко не все библиотеки имеют интерфейс с промисами и работают по старинке, на колбеках. В таких случаях функции нужно "обернуть" или, как говорят, "промисифицировать". Создание промиса происходит с помощью конструктора Promise:</p>
1
<p>Если в проекте появились промисы, то, по-хорошему, весь код должен работать только через них. К сожалению, далеко не все библиотеки имеют интерфейс с промисами и работают по старинке, на колбеках. В таких случаях функции нужно "обернуть" или, как говорят, "промисифицировать". Создание промиса происходит с помощью конструктора Promise:</p>
2
<p>Промис ожидает на вход функцию, которая будет вызвана в момент его создания. Именно внутри этой функции и нужно выполнять асинхронную операцию (на колбеках), которую мы хотим превратить в промис. Промис прокидывает в эту функцию два колбека:</p>
2
<p>Промис ожидает на вход функцию, которая будет вызвана в момент его создания. Именно внутри этой функции и нужно выполнять асинхронную операцию (на колбеках), которую мы хотим превратить в промис. Промис прокидывает в эту функцию два колбека:</p>
3
<ul><li>resolve - должна быть вызвана в случае успешного завершения асинхронной операции. Ей на вход отдаётся результат этой операции.</li>
3
<ul><li>resolve - должна быть вызвана в случае успешного завершения асинхронной операции. Ей на вход отдаётся результат этой операции.</li>
4
<li>reject - должна быть вызвана в случае ошибки. На вход, соответственно, отдаётся ошибка.</li>
4
<li>reject - должна быть вызвана в случае ошибки. На вход, соответственно, отдаётся ошибка.</li>
5
</ul><p>Эти функции принимают на вход ровно один аргумент, который затем передаётся либо в then (как данные), либо в catch (как ошибка). Причём достаточно, чтобы вызывалась хотя бы одна из этих функций. Вполне возможно, что понадобится создать промис, который всегда завершается успешно - и это легко сделать, никогда не вызывая reject.</p>
5
</ul><p>Эти функции принимают на вход ровно один аргумент, который затем передаётся либо в then (как данные), либо в catch (как ошибка). Причём достаточно, чтобы вызывалась хотя бы одна из этих функций. Вполне возможно, что понадобится создать промис, который всегда завершается успешно - и это легко сделать, никогда не вызывая reject.</p>
6
<p>В конечном итоге конструкция new Promise() возвращает самый настоящий промис, с которым можно работать уже привычным для нас способом:</p>
6
<p>В конечном итоге конструкция new Promise() возвращает самый настоящий промис, с которым можно работать уже привычным для нас способом:</p>
7
<p>А что, если нужно обернуть две асинхронных операции или три, или даже больше? Придётся оборачивать каждую из них независимо. Другими словами, одна асинхронная операция - один конструктор new Promise. Кстати, эту задачу можно автоматизировать, и в ноду встроена специальная функция, которая делает промисы из асинхронных функций:</p>
7
<p>А что, если нужно обернуть две асинхронных операции или три, или даже больше? Придётся оборачивать каждую из них независимо. Другими словами, одна асинхронная операция - один конструктор new Promise. Кстати, эту задачу можно автоматизировать, и в ноду встроена специальная функция, которая делает промисы из асинхронных функций:</p>
8
<p>Во фронтенде такое тоже возможно, достаточно "загуглить" пакет, предоставляющий функцию promisify.</p>
8
<p>Во фронтенде такое тоже возможно, достаточно "загуглить" пакет, предоставляющий функцию promisify.</p>
9
<p>В реальной жизни встречаются задачи, когда асинхронного кода нет, но нужен промис, чтобы построить цепочку. Такой промис можно создать самостоятельно:</p>
9
<p>В реальной жизни встречаются задачи, когда асинхронного кода нет, но нужен промис, чтобы построить цепочку. Такой промис можно создать самостоятельно:</p>
10
<p>То же самое для промиса, который завершается неуспешно:</p>
10
<p>То же самое для промиса, который завершается неуспешно:</p>
11
<p>Для этих задач добавили специальные сокращения, с которыми код становится чище:</p>
11
<p>Для этих задач добавили специальные сокращения, с которыми код становится чище:</p>
12
<h2>Устройство</h2>
12
<h2>Устройство</h2>
13
<p>С технической точки зрения, промис - это объект, имеющий три состояния (см. конечные автоматы и автоматное программирование):<em>pending</em>,<em>fulfilled</em>и<em>rejected</em>. Промис начинается в состоянии<em>pending</em>, а затем, с помощью функций ("событий", как говорят в теории автоматов) resolve и reject переводится в одно из конечных (терминальных) состояний<em>fulfilled</em>или<em>rejected</em>. Перейдя однажды в эти состояния, промис уже не может откатиться назад или уйти в другое терминальное состояние. То есть после вызова resolve, нет способа привести промис в состояние<em>rejected</em>, вызывая функцию reject.</p>
13
<p>С технической точки зрения, промис - это объект, имеющий три состояния (см. конечные автоматы и автоматное программирование):<em>pending</em>,<em>fulfilled</em>и<em>rejected</em>. Промис начинается в состоянии<em>pending</em>, а затем, с помощью функций ("событий", как говорят в теории автоматов) resolve и reject переводится в одно из конечных (терминальных) состояний<em>fulfilled</em>или<em>rejected</em>. Перейдя однажды в эти состояния, промис уже не может откатиться назад или уйти в другое терминальное состояние. То есть после вызова resolve, нет способа привести промис в состояние<em>rejected</em>, вызывая функцию reject.</p>