<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Anna</title>
    <description>The latest articles on Forem by Anna (@ukraintseva).</description>
    <link>https://forem.com/ukraintseva</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3346411%2Fd18f9898-877a-4cb0-ae73-b127be4341dd.jpg</url>
      <title>Forem: Anna</title>
      <link>https://forem.com/ukraintseva</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ukraintseva"/>
    <language>en</language>
    <item>
      <title>BFF: Секретное оружие фронтенда в мире микросервисов</title>
      <dc:creator>Anna</dc:creator>
      <pubDate>Wed, 01 Oct 2025 10:08:07 +0000</pubDate>
      <link>https://forem.com/ukraintseva/bff-siekrietnoie-oruzhiie-frontienda-v-mirie-mikrosiervisov-1lj9</link>
      <guid>https://forem.com/ukraintseva/bff-siekrietnoie-oruzhiie-frontienda-v-mirie-mikrosiervisov-1lj9</guid>
      <description>&lt;p&gt;Представим себе такую ситуацию, что backend часть проекта разбросана по разным микросервисам, например, нам необходимо загрузить страницу, на которой отображается информация пользователя с его уведомлениями, а также таблица с необходимой информацией, все эти данные разбросаны по разным микросервисам, то есть, чтобы получить данную информацию нам необходимо "стучаться" по разным URL, при этом следить чтобы запросы отправлялись в правильной последовательности.&lt;br&gt;
Данный процесс довольно трудоемкий, но что если есть способ решения данной проблемы? &lt;/p&gt;

&lt;p&gt;Именно здесь появляется &lt;strong&gt;BFF (Backend For Frontend)&lt;/strong&gt; - это архитектурный паттерн, основная идея которого - это создание отдельного серверного слоя, который представляет из себя прокси сервер, то есть он занимается отправкой запроса на нужный сервис и преобразует ответ в вид, который необходим фронтенду.&lt;/p&gt;

&lt;p&gt;Самой наилучшей аналогией, которая представляет BFF является официант. Когда мы приходим в ресторан, то вместо того, чтобы бегать к каждому повару отдельно за необходимыми заказами(делать запросы к разным сервисам), мы работаем с официантом(BFF), мы предоставляем ему информацию о том, какие блюда нам нужны(один запрос к BFF), а официант сам передаст информацию необходимым поварам, соберет все заказы и принес нам за стол.&lt;/p&gt;

&lt;p&gt;В данной статье мы разберем BFF и его тонкости.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Что такое BFF? Основные концепции&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Мы уже сделали вывод, что BFF - это персональный backend для нашего frontend.&lt;/p&gt;

&lt;p&gt;Основная идея данного паттерна заключается в том, что каждый клиент, будь то веб-приложение, мобильное приложение и тд имеет свой "сервер-компаньон", который:&lt;br&gt;
1) Знает его специфические требования (например, нам необходимо отправлять на мобильное приложение ответ с меньшим кол-вом полей, чем на веб-приложение)&lt;br&gt;
2) Оптимизирует работу с серверной частью приложения&lt;br&gt;
3) Предоставляет специализированный API для конкретного UI&lt;/p&gt;

&lt;p&gt;При этом важно понимать, что BFF - это архитектурный паттерн, который реализовывает связь между клиентом и сервером, а не фреймворк или библиотека.&lt;/p&gt;

&lt;p&gt;Ключевый характеристики BFF:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Индивидуальность&lt;/strong&gt;&lt;br&gt;
BFF создается для конкретного клиента и "заточен" на:&lt;br&gt;
1) Особенности отображения данных на клиенте.&lt;br&gt;
2) Особенности сетевого взаимодействия.&lt;br&gt;
3) Специфические требования к формату данных.&lt;br&gt;
4) Оптимальные стратегии кэширования данных.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;"Тонкий" сетевой слой&lt;/strong&gt;&lt;br&gt;
BFF не должно содержать бизнес логики, является крайне важно. Основные функции BFF:&lt;br&gt;
1) Агрегация данных - получение необходимых данных из разных сервисов в единую модель.&lt;br&gt;
2) Трансформация данных под клиентские нужны.&lt;br&gt;
3) Маршрутизация запросов к необходимым сервисам.&lt;br&gt;
4) Обработка ошибок.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Использование данного паттерна в настоящее время становится частой практикой среди frontend сообщества, это связано стем, что:&lt;br&gt;
1) Микросервисная архитектура все чаще и чаще используется на проектах.&lt;br&gt;
2) Большое разнообразие клиентских устройств.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Архитектура BFF в деталях&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Рассмотрим общую схему работы BFF:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa2juxn2ku27ojgx3ox3r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa2juxn2ku27ojgx3ox3r.png" alt="Общая схема работы BFF" width="520" height="780"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Как запросы проходят через BFF:&lt;br&gt;
1) Запрос с клиента - frontend отправляет один запрос к BFF.&lt;br&gt;
2) Данные попадают в прослойку и начинается работа BFF архитектуры.&lt;br&gt;
3) Аутентификация - проверка токенов и параметров.&lt;br&gt;
4) Параллельные запросы - обращение к микросервисам, которые необходимы.&lt;br&gt;
5) Агрегация данных - объединение результатов по запросам к микросервисам.&lt;br&gt;
6) Трансформация данных - преобразование данных в необходимый для клиента вид.&lt;br&gt;
7) Ответ на клиент - передача сформированного ответа на сторону frontend.&lt;/p&gt;

&lt;p&gt;BFF состоит из нескольких логических компонентов:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Маршрутизатор&lt;/strong&gt;, который определяет, какой обработчик должен выполнить запрос и провалидировать данные.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Пример маршрутизации с Express.js&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/web/products/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;productPageHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/web/user-profile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userProfileHandler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Агрегатор данных&lt;/strong&gt; (Data aggregator), который управляет параллельными запросами и объединяет их результаты.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DataAggregator&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;aggregateProductPageData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reviews&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;recommendations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;catalogService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reviewService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getReviews&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;recommendationService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSimilar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inventoryService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getStockInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reviews&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;recommendations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stock&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Трансформеры&lt;/strong&gt; (Transformers), которые преобразуют данные в формат необходимый клиенту.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductTransformer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;transformForWeb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reviews&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;recommendations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stock&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;productInfo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="na"&gt;reviews&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;reviews&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="na"&gt;recommendations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;recommendations&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rec&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;product_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;})),&lt;/span&gt;
            &lt;span class="na"&gt;availability&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Клиенты микросервисов&lt;/strong&gt; (Service Clients), которые специализируются на работе с каждым микросервисом, они формируют HTTP-запросы, обрабатывают ошибки и timeout.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;BFF и Микрофронтенды&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Когда мы работаем с микрофронтендами, то мы разбиваем монолитное приложение на части. Каждый отдельный микрофронтенд (MFE) разрабатывается и деплоится независимо, но должны работать вместе, как единое целое. Тут возникает несколько проблем: каждый MFE делает запросы напрямую к микросервисам, данная логика может дублироваться в разных MFE, что может привести к сложностям реализации MFE или же нарушению принципа независимости.&lt;/p&gt;

&lt;p&gt;Когда мы используем BFF совместно с микрофронтендами, то существует несколько подходов:&lt;br&gt;
1) Специализированный BFF для каждого MFE - каждый микрофронтенд имеет собственный BFF, они вместе разрабатывается и деплоятся.&lt;br&gt;
2) Единый BFF с модульной структурой - единый BFF-сервер с четким разделением на модули для каждого MFE.&lt;/p&gt;

&lt;p&gt;BFF + микрофрентенды имеют следующие преимущества:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Полная независимость.&lt;/li&gt;
&lt;li&gt;Оптимизированная загрузка данных.&lt;/li&gt;
&lt;li&gt;Устойчивость к изменениям.&lt;/li&gt;
&lt;li&gt;Единая точка управления.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Данный подход позволяет работать независимо, ускоряет разработку и повышает надежность приложения. BFF - дает нам контроль над данными и позволяет создавать эффективные приложения.&lt;/p&gt;

&lt;p&gt;BFF - это первый шаг к улучшению архитектуры, результат не заставит себя долго ждать.&lt;/p&gt;

&lt;p&gt;Время стоить архитектуру, которая работает на вас, а не наоборот.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>microservices</category>
      <category>frontend</category>
      <category>architecture</category>
    </item>
    <item>
      <title>this не магия: практическое руководство по контексту выполнения в JavaScript</title>
      <dc:creator>Anna</dc:creator>
      <pubDate>Tue, 16 Sep 2025 17:58:18 +0000</pubDate>
      <link>https://forem.com/ukraintseva/this-nie-maghiia-praktichieskoie-rukovodstvo-po-kontiekstu-vypolnieniia-v-javascript-328j</link>
      <guid>https://forem.com/ukraintseva/this-nie-maghiia-praktichieskoie-rukovodstvo-po-kontiekstu-vypolnieniia-v-javascript-328j</guid>
      <description>&lt;p&gt;Если бы у JavaScript был конкурс на самую запутанную концепцию, то первое место уверенно заняло ключевое слово this, его поведение на первый взгляд кажется непредсказуемым, но на самом деле это не так.&lt;/p&gt;

&lt;p&gt;А причина такой путаницы в том, что this в отличии от других переменных не имеет жёсткой привязки, его значение нельзя посмотреть в момент объявления функции, ведь оно определяется в момент вызова функции. Даже если мы будем сравнивать контекст в обычных и стрелочных функциях результат может отличаться.&lt;/p&gt;

&lt;p&gt;Самая лучшая аналогия про this - это аналогия со словом "я". Значение этого слова полностью зависит от того, кто его произносит. Если скажете вы, то "я" - это вы, если ваш друг, то это он и так далее. Также и с контекстом, this - это слово "я" внутри функции.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Основные проблемы, возникающие с this&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Один и тот же код, но разные результаты&lt;/li&gt;
&lt;li&gt;Возможность возникновения потери контекста&lt;/li&gt;
&lt;li&gt;Кажущаяся сложность&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Цель данной статьи - разобрать правила определения this и убрать страх перед использованием контекста.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Что такое this?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;this - это ключевое слово, которое пришло в JavaScript для того, чтобы помочь в реализации объектно-ориентированного программирования. Если говорить проще, то this - это ссылка на некий объект, к свойствам которого можно обратиться внутри вызова функции. this также называют контекстом выполнения.&lt;br&gt;
Это специальная переменная, которая автоматически создается внутри каждой функции(за некоторым исключением, о котором мы поговорим позже) в момент её выполнения.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ключевая характеристика контекста вызова - это её динамичность, то есть значение this определяется в момент вызова функции, а не в момент создания. Это является фундаментальным отличием между контекстом вызова и переменными, которые имеют область видимости&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Режим исполнения и глобальный объект&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Для начала разберем самые простые правила, когда функция вызывается сама по себе, без какого-либо контекста, так сказать "голая". Здесь в игру вступает режим исполнения, который напрямую влияет на состояние контекста вызова.&lt;/p&gt;

&lt;p&gt;Разберемся что такого глобальный объект.&lt;br&gt;
Глобальный объект в JavaScript - это корневой объект, переменные и функции которого доступны в любом месте программы. Данный объект представляет из себя глобальную область видимости, если мы говорим про frontend разработку, то в браузере глобальный объект - это window.&lt;/p&gt;

&lt;p&gt;Мы разобрались, что такое глобальный объект, теперь разберемся, для чего нам это нужно. Когда скрипт выполняется, он может быть вызван в одном из двух режимов:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Нестрогий(режим по умолчанию)&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Строгий(use strict)&lt;br&gt;
Данные режимы определяют поведение контекста при вызове функций.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Если функция вызывается, как независимая функция и выполняется в нестрогом режиме, то this будет ссылаться на глобальный объект:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkThis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;checkThis&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="c1"&gt;// В браузере будет выведен глобальный объект window&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Если мы захотим изменить свойства объекта через this, то это может привести к ошибкам и мы можем изменить свойства глобального объекта, поэтому чаще всего используют строгий режим.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Если функция будет вызвана, как независимая функция, но в строгом режиме, то ответ будет отличаться, значение this в данной функции будет становиться undefined:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use strict&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Включение строгого режима&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;checkThisStrict&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;checkThisStrict&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="c1"&gt;// В результате будет undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Это более безопасное поведение, обращение к полям такого объекта вызовет ошибку, которую будет легко обнаружить.&lt;/p&gt;

&lt;p&gt;Данное поведение является базовым, все остальные правила - это способ переопределить поведение и явно указать функции, на что должно ссылаться ключевое слово this.&lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;Основных правила определения this&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Понимание контекста вызова строится на четырех основным правилах, по которым компилятор определяет значение this. То есть, чтобы найти контекст вызова необходимо последовательно проверять условия каждого правила.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Правило 1: Простой вызов (Default Binding)&lt;/strong&gt;&lt;br&gt;
Функция, которая вызывается сама по себе, без каких-либо дополнений. Данное поведение мы рассмотрели выше, поведение в строгом и нестрогом режимах. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Важно:&lt;/strong&gt; это правило срабатывает чаще всего там, где мы не ожидаем, особенно при работе с callback.&lt;/p&gt;

&lt;p&gt;Рассмотрим пример с использованием "голых" функций:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;local&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;global&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// global&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Разберемся, почему конечный вывод именно такой. Как известно, переменная, объявленная с помощью var попадает в глобальную область видимости, именно поэтому, когда мы вызываем независимую функцию в нестрогом режиме, то в нее попадает значение, хранящееся в глобальной области видимости (window.bar).&lt;/p&gt;

&lt;p&gt;Пример с callback мы разберем позже, чтобы лучше понять материал.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Правило 2: Вызов как метода объекта (Implicit Binding)&lt;/strong&gt;&lt;br&gt;
Функция, которая вызывается как метод объекта, то есть через точку или квадратные скобки. В данном случае this будет ссылаться на сам объект, который стоит перед точкой в момент вызова.&lt;br&gt;
Рассмотрим пример:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Анна&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;logName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;logName&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Выведет "Анна"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Мы создали объект, внутри которого прописали функцию вывода имени пользователя. Как мы уже сказали выше, контекст вызова будет ссылаться на объект перед точкой, как мы видим из строчки &lt;code&gt;user.logName();&lt;/code&gt;, объект перед точкой - это user, значит this = user.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Важно:&lt;/strong&gt; this определяется в момент вызова, а не в момент создания.&lt;/p&gt;

&lt;p&gt;На основе этой информации рассмотрим еще несколько примеров:&lt;/p&gt;

&lt;p&gt;Пример №1&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Анна&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;logName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Создаем новую переменную, которая ссылается на функцию logName&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;logNameFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logName&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Вызываем функцию без объекта перед точкой.&lt;/span&gt;
&lt;span class="nf"&gt;logNameFunction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// undefined или ''&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;В результате мы получим не совсем тот результат, который мы ожидали, разберемся, почему это происходит.&lt;br&gt;
Мы создали объект точно также, как и в предыдущем примере, но при этом результат получило совершенно иной. Это связано с тем, как мы вызываем метод объекта, в данном случае, мы функцию кладем в переменную logNameFunction, это действие эквивалентно следующему коду:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;logNameFunction&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Поэтому, когда мы вызываем данную функцию, она действует по правилу 1, то есть ссылается на глобальный объект.&lt;/p&gt;

&lt;p&gt;Пример №2&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Анна&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;logName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Правило 2: вызов как метода объекта. Сработает.&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;logName&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Анна&lt;/span&gt;

&lt;span class="c1"&gt;// А теперь передадим метод как колбэк&lt;/span&gt;
&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// undefined или ''&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;В данном примере похожая ситуация, внутрь setTimeout мы передали ссылку на функцию из объекта, как callback функцию, именно поэтому, в момент вызова этой функции она ссылается на глобальный объект. Но данную ситуацию можно исправить.&lt;br&gt;
Как уже говорилось выше, контекст вызова определяется в момент вызова, значит нужно сделать так, чтобы в момент вызова функции она ссылалась на объект.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;()},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="c1"&gt;// Анна&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;При такой записи мы не теряем контекст за счет того, что вызов происходит сразу, когда this ссылается на объект user. Есть и другие способы решения этой проблемы, рассмотрим их позже.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;В рассмотренных выше примерах показывается самая частая проблема при работе с контекстом - потеря контекста, когда this не указывает на объект, откуда функция была взята.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Правило 3: Явное указание контекста (Explicit Binding)&lt;/strong&gt;&lt;br&gt;
В JavaScript мы можем явно указать какой объект должен использоваться в качестве контекста вызова. Для этих целей методы call, apply, bind.&lt;/p&gt;

&lt;p&gt;Методы call и apply очень похожи, их разница в том, как мы передаем аргументы в функцию, поэтому рассмотрим их в связке.&lt;br&gt;
Данные методы позволяют вызывать функции в контексте других объектов, иными словами, мы явно указываем контекст вызова this. Особенностью данных методов является то, что они немедленно вызывают функцию.&lt;br&gt;
Синтаксис:&lt;br&gt;
func.call(this, arg1, arg2, ...)&lt;br&gt;
func.apply(this, [arg1, arg2, ...])&lt;br&gt;
Как можно заметить, разница данных методов в синтаксе, а именно в том, как передаются аргументы в функцию.&lt;/p&gt;

&lt;p&gt;Метод bind очень похож на предшественников, но его отличие в том, что данный метод НЕ вызывает функцию сразу, он возвращает новую функцию, которая будет привязана к необходимому контексту.&lt;br&gt;
Синтаксис: &lt;br&gt;
func.bind(this, arg1, arg2, ...)&lt;/p&gt;

&lt;p&gt;Теперь мы можем дать еще одно решение для проблемы потери контекста из примера №2.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Анна&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;В данном случае, мы привязали объект, поэтому в момент вызова функции, контекст вызова будет равен объекту user, что решает нашу проблему.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Правило 4: Вызов с оператором new (New Binding)&lt;/strong&gt;&lt;br&gt;
В JavaScript можно создавать функции-конструктор с помощью оператора new.&lt;br&gt;
Функция-конструктор - это специальная функция, предназначенная для создания объектов. Чаще всего функции-конструкторы применяют для создания объектов по шаблону. Внутри такой функции this будет ссылаться на новосозданный пустой объект.&lt;/p&gt;

&lt;p&gt;Рассмотрим пример создания функции-конструктора:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// В данный момент this = {}&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isAdmin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userAnna&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Анна&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userAnna&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'Анна'&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userAnna&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 25&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;При этом, в случае, если мы неправильно создадим объект, то есть без оператора new, то поведение будет совсем иное, тогда контекст вызова будет работать по правилу 1 и ссылаться на глобальный объект.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Важно:&lt;/strong&gt; всегда использовать new с функциями-конструкторами.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Приоритет правил&lt;/strong&gt;&lt;br&gt;
Может случиться так, что к this подходят сразу несколько правил, на этот случай в JavaScript есть приоритет правил, рассмотрим от высшего приоритета к низшему.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;new (Правило 4) имеет самый высокий приоритет, в функции-конструкторе this - это всегда новый объект.&lt;/li&gt;
&lt;li&gt;Явная привязка (Правило 3), когда привязываем контекст с помощью call, apply, bind.&lt;/li&gt;
&lt;li&gt;Неявная привязка (Правило 2), вызов функции через метод объекта.&lt;/li&gt;
&lt;li&gt;Простой вызов (Правило 1) имеет самый низкий приоритет, контекст ссылается на глобальный объект, зависит от строгого или нестрогого режима.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Рассмотрим пример:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Анна&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// Правило 1&lt;/span&gt;
&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;

&lt;span class="c1"&gt;// Правило 2&lt;/span&gt;
&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getName&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "Анна"&lt;/span&gt;

&lt;span class="c1"&gt;// Правило 3&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;boundFoo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;boundFoo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// "Анна"&lt;/span&gt;

&lt;span class="c1"&gt;// Правило 4&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newObj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;boundFoo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;На данном примере хорошо видна приоритезация между правилами 3 и 4. Почему в последней строке выводится undefined, хотя контекст явно привязан через метод bind? Как и говорилось выше, при использовании new контекст вызова - это пустой массив, то есть this = {}, внутри этого объекта нет свойства name, именно поэтому мы и получаем такой ответ.&lt;/p&gt;

&lt;p&gt;Мы рассмотрели все правила и их приоритет, теперь определять, чему равен this намного проще.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Особое поведение: Стрелочные функции&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Стрелочные функции ведут себя иначе с точки зрения контекста вызова по сравнению с обычными функциями. &lt;strong&gt;Главное правило стрелочной функции - это то, что у нее нет своего this.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Внутри стрелочной функции контекст берется извне, то есть она не создает свой контекст исполнения, а ссылает на объект ближайший по иерархии. Это называется "лексический this".&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Если говорить проще, то this внутри стрелочной функции равно this снаружи её.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Рассмотрим пример использования контекста со стрелочной функцией и когда это будет полезно:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Анна&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Обычная функция:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// undefined или ''&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Стрелочная функция:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 'Анна'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;При вызове через обычную функцию, у нас произойдет потеря контекста, так как функция вызывается сама по себе позже и подчиняется правилу 1, обращаясь к глобальному объекту. Вызов через стрелочную функцию решит данную проблему, потому что у нее нет своего контекста, и она обращается к  внешнему this из функции greet, а внутри нее по правилу 2 контекст равен user, стрелочная функция "запомнила" это значение и использует его всегда, когда бы не вызвали.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Важно:&lt;/strong&gt; к стрелочным функциям нельзя применять методы call, apply и bind, this внутри таких функций зафиксирован и не меняется.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Важно:&lt;/strong&gt; стрелочные функции не могут быть конструкторами, вызов функции с new выбросит ошибку.&lt;/p&gt;

&lt;p&gt;Использовать стрелочных функций с контекстом вызова лучше всего в callback функциях, так как это уберегает от потери контекста.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;this в обработчиках событий DOM&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Ключевая задача frontend разработчика - это работа с DOM деревом, в JavaScript также есть правила работы с контекстом в обработчиках событий.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Стандартное поведение - обычные функции обработчики&lt;/strong&gt;&lt;br&gt;
Когда мы создаем прослушиватель событий и назначает обычную функцию обработчик, то в данном случае &lt;strong&gt;this ссылается на  DOM-элемент, на котором событие было вызвано.&lt;/strong&gt;&lt;br&gt;
При вызове addEventListener он неявно привязывает контекст вызова к элементу, на котором случилось событие.&lt;/p&gt;

&lt;p&gt;Рассмотрим пример:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myBtn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// this внутри этой обычной функции будет указывать на элемент button&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Выведет: &amp;lt;button id="myBtn"&amp;gt;Нажми меня&amp;lt;/button&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Выведет: 'myBtn'&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Выведет: 'Нажми меня'&lt;/span&gt;

  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backgroundColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Можно напрямую менять стили элемента&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Данное поведение удобно, потому что дает прямой доступ к элементу, с которым происходит взаимодействие.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Исключение - стрелочные функции обработчики&lt;/strong&gt;&lt;br&gt;
Если использовать стрелочную функцию в качестве обработчика, то поведение с this меняется. &lt;strong&gt;Внутри стрелочной функции-обработчика контекст this будет равен контексту той функции, внутри которой она была вызвана.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Пример с кнопкой и стрелочной функцией:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;myBtn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// window или undefined&lt;/span&gt;

  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;backgroundColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="c1"&gt;// строка вызовет ошибку в строгом режиме&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Лучше всего использовать стрелочные функции-обработчики, когда необходим доступ к внешнему элементу, чаще всего это используется в экземплярах класса.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Специальные случаи и тонкости&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Мы изучили основные правила и особенности, которые важно знать для того, чтобы работать с ключевым словом this, но остались некоторые нюансы, которые будет полезно знать.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;this в методах массива (forEach, map, filter и т.д.)&lt;/strong&gt;&lt;br&gt;
У методов массивов, которые принимают callback функции, например: forEach, map, filter, some, every и прочие, есть второй параметр, который является необязательным. Это объект, который будет использоваться в качестве this, то есть можно сказать, что это аналог явной привязки с помощью  call, apply, bind.&lt;br&gt;
Синтаксис:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;thisArg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Рассмотрим пример с методом map:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;validator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;min&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resultBad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resultBad&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// [false, false, false, false] &lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resultGood&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="c1"&gt;// [false, true, false, false] &lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resultGood&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;В случае, когда мы вызываем метод map без второго аргумента, то происходит потеря контекста и внутри функции this ссылается на глобальный объект, со вторым параметром ситуацию координально меняется, потеря контекста не происходит и функция отрабатывает корректно.&lt;/p&gt;

&lt;p&gt;Альтернативным способом является переписать callback функцию внутри метода, чтобы this ссылалось на верные данные. Пример реализации:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resultBad&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;validator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;this в конструкторах встроенных объектов&lt;/strong&gt;&lt;br&gt;
Многие встроенные в JavaScript конструкторы, например, такие как Promise, Set, Map, Date имеют особенности при работе с контекстом вызова, они сами управляют контекстом и внутри них он обычно равен undefined(в строгом режиме).&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Итог: Алгоритм определения this для любой функции&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Подведем итог и выявим алгоритм для определения контекста.&lt;/p&gt;

&lt;p&gt;Задаем вопросы по порядку, как только условие шага выполняется, то ответ найден.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Функция вызвана с помощью оператора new?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ДА --&amp;gt; Значит this ссылается на пустой только что созданный объект.&lt;br&gt;
НЕТ --&amp;gt; Переходим к следующему шагу&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Функция вызвана с помощью методов call, apply, bind?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ДА --&amp;gt; Значит this ссылается на объект переданный в метод.&lt;br&gt;
НЕТ --&amp;gt; Переходим к следующему шагу&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Функция &lt;strong&gt;вызвана&lt;/strong&gt; как метод объекта?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ДА --&amp;gt; Значит this ссылается на объект перед точкой.&lt;br&gt;
НЕТ --&amp;gt; Переходим к следующему шагу&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Это стрелочная функция?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;ДА --&amp;gt; Значит this ссылается на контекст, который находится выше по иерархии на момент ее объявления.&lt;br&gt;
НЕТ --&amp;gt; Переходим к следующему шагу&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;В иных случаях - это простой вызов функции&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Значит this ссылается на глобальный объект, если это нестрогий режим и undefined, если строгий режим.&lt;br&gt;
Простая блок схема для определения значения this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8fob4bxkbhts7y1df0k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv8fob4bxkbhts7y1df0k.png" alt="Блок схема поиска this" width="760" height="1095"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Заключение&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Тема контекста this в JavaScript является одной из самых сложных, но после изучения всех тонкостей поведение контекста становится предсказуемым.&lt;/p&gt;

&lt;p&gt;Ключевые выводы, которые можно сделать по этой теме:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Контекст определяется в момент &lt;strong&gt;вызова&lt;/strong&gt; функции, а не в момент объявления.&lt;/li&gt;
&lt;li&gt;Существует два координально разных типа функций с точки зрения контекста: обычные и стрелочные функции.&lt;/li&gt;
&lt;li&gt;Необходимо подбирать инструменты под определенные задачи.&lt;/li&gt;
&lt;li&gt;Существует проблема потери контекста, бороться с ней можно, при этом важно понимать причину.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;this понятен. Можно идти дальше :)&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>frontend</category>
      <category>typescript</category>
      <category>interview</category>
    </item>
    <item>
      <title>Promise полный гид для понятного кода</title>
      <dc:creator>Anna</dc:creator>
      <pubDate>Tue, 09 Sep 2025 19:26:54 +0000</pubDate>
      <link>https://forem.com/ukraintseva/asinkhronnyi-javascript-polnyi-ghid-po-promise-dlia-poniatnogho-koda-4oho</link>
      <guid>https://forem.com/ukraintseva/asinkhronnyi-javascript-polnyi-ghid-po-promise-dlia-poniatnogho-koda-4oho</guid>
      <description>&lt;p&gt;Ранее JavaScript не обладал механизмами для работы с асинхронным кодом, к которым все уже привыкли. Изначальным и единственным инструментом для обработки операций, время выполнения которых было неизвестно, были callback функции, или функции обратного вызова.&lt;/p&gt;

&lt;p&gt;Callback функция в JavaScript - функция, которая передается в другую функцию в качестве аргумента.&lt;/p&gt;

&lt;p&gt;Приведем пример функции callback:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;first&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;second&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;В ответе мы получим следующий результат:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1
2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Кажется, что может быть проще, но данный паттерн имеет проблемы при масштабировании сложных приложений. Данная ситуация называется callback hell.&lt;/p&gt;

&lt;p&gt;Callback Hell в JavaScript возникает при выполнении слишком большого кол-ва функций обратного вызова.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Чем больше callback функций мы используем, тем сложнее читать, поддерживать и анализировать код, что может привести к различного рода ошибкам и затруднить отладку и предсказуемость поведения.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Рассмотрим наглядный пример:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;asyncFirst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;asyncSecond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;asyncThird&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;asyncFirst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;asyncSecond&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;asyncThird&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Мы рассмотрели вариант callback hell, но в данном случае мы видим, что у пирамиды высота равна трем, представим, как громоздко будет выглядеть код с большей высотой пирамиды.&lt;/p&gt;

&lt;p&gt;Из-за роста сложности приложений на JavaScript паттерн использования функций обратного вызова себя исчерпал, поэтому была придумана новая и более мощная абстракция, которая была сформирована в спецификации ES6 и носила название Promise.&lt;/p&gt;

&lt;p&gt;Promise в JavaScript - специализированный объект, который предоставляет удобный способ организации асинхронного кода.&lt;/p&gt;

&lt;p&gt;В данной статье будет проведен детальный анализ объекта Promise, чтобы предоставить понимание данного механизма, необходимого для современной разработки на JavaScript.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Жизненный цикл Promise&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Promise может находиться в 3 состояниях:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;pending(ожидание) - начальное состояние объекта, после его создания, на данном этапе promise не исполнен и не отклонен.&lt;/li&gt;
&lt;li&gt;fulfilled(исполнено) - состояние объекта после успешного завершения операции. Переход в данное состояние происходит в момент вызова функции resolve внутри promise.&lt;/li&gt;
&lt;li&gt;rejected(отклонено) - состояние объекта после завершения операции с ошибкой. Переход в данное состояние происходит в момент вызова функции rejected внутри promise.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;_Важно запомнить, что переход promise из состояния pending в fulfilled или rejected является необратимым, то есть, мы можем получить только успешное завершение операции или завершение с ошибкой, изменить это состояние не получится. Это гарантирует предсказуемость операции. _&lt;/p&gt;

&lt;p&gt;Завершенный promise - это тот, который перешел в состояние fulfilled или rejected(данный термин мы еще будем использовать).&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Создание Promise&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Для создания Promise используется конструктор &lt;code&gt;new Promise()&lt;/code&gt;, а внутрь передается специальная функция-исполнитель, именно в этой функции заключается вся логика операции, которую должен обернуть Promise.&lt;/p&gt;

&lt;p&gt;Функция исполнитель вызывается синхронно, когда создается Promise. Она принимает два аргумент:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;resolve - функция, которую необходимо вызвать, чтобы promise успешно завершился. Аргументом данной функции является значение выполняемого promise, то есть то, что мы получили в ходе выполнения асинхронной операции.&lt;/li&gt;
&lt;li&gt;reject - функция, которую необходимо вызвать, чтобы promise завершился с ошибкой. В качестве аргумента передать значение, которое станет причиной отклонения данной операции.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Приведем пример:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Start&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Имитируем асинхронную операцию&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt; 
    &lt;span class="c1"&gt;// Успешное завершение&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Завершение с ошибкой&lt;/span&gt;
    &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;&lt;span class="c1"&gt;// или throw new Error("Error");&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Функция исполнитель НЕ является асинхронной сама по себе, асинхронную операцию мы инициализируем внутри данной функции, это может быть обращение к серверу, работа с файлами и т.д.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Если внутри Promise не вызвать resolve или reject, она так и останется в состоянии pending и никогда не будет завершена.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Методы .then(), .catch(), .finally()&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Мы написали Promise, теперь нам необходимо извлечь и обработать данные, которые мы отправили через resolve или reject. Для того, чтобы это сделать существуют методы then(), .catch(), .finally(). Эти методы регистрируют функции-обработчики, которые будут вызваны автоматически, когда Promise перейдет в соответствующее состояние.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;then() - метод, который является основным для обработки результата, он подходит как для обработки успешного выполнения, так и для завершения с ошибкой. Принимает два аргумента:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;onFulfilled - функция, которая будет вызвана, когда Promise завершится с успехом.&lt;/li&gt;
&lt;li&gt;onRejected - функция, которая будет вызвана, когда Promise завершится с ошибкой.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Рассмотрим пример обработки функции, которую мы писали выше:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Полученные данные по пользователю:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ошибка:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Чаще всего в функцию передается первый аргумент, а ошибка обрабатывается в методе catch()&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;catch() - метод для обработки ошибок, имеет один аргумент - функция для обработки ошибок, такая же, как если бы мы передавали второй аргумент в метод then(). Только в данном случае catch() - это упрощенный и более читаемый синтаксис для регистрации обработчика ошибок.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Рассмотрим пример обработки ошибок функции getData:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ошибка:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;//Или второй вариант написания&lt;/span&gt;
&lt;span class="nx"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ошибка:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;finally() - метод, который выполняется в любом случае, независимо от того завершился Promise успешно или с ошибкой. Этот метод позволяет избежать дублирования в методах then() и catch(). Данный метод не принимает никаких аргументов, а также не возвращает никакие значения.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Рассмотрим пример:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Успех&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ошибка&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Завершено&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;})&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Так в случае успешного завершения Promise мы увидим:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Успех
Завершено
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;А в случае завершения с ошибкой:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ошибка
Завершено
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Но и это еще не все, каждый из методов then(), catch(), finally() возращает тоже Promise, а это значит, что мы можем реализовать так называемые цепочки вызовов. Благодаря этому можно обработать несколько асинхронных операций одна за другой.&lt;/p&gt;

&lt;p&gt;Разберемся, как это работает. Как говорилось выше, методы возвращают Promise, а значит можно продолжить цепочку дальше, в качестве их аргументов будут выступать результаты предыдущих методов. Легче разобраться на практике.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Успех&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;getData&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; 2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; 3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;В результате мы получим:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Успех
Успех 2
Успех 2 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Рассмотрим выполнение кода поэтапно:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Мы создали Promise getData, который с помощью resolve переводит состояние Promise в fulfilled со значением "Успех".&lt;/li&gt;
&lt;li&gt;Обрабатываем с помощью then(), в качестве аргумента в функцию будет передаваться значение "Успех".&lt;/li&gt;
&lt;li&gt;При обработке снова возвращаем значение, которое переходит в следующий метод then()&lt;/li&gt;
&lt;li&gt;Далее алгоритм повторяется.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;То же самое происходит с методами catch() и finally().&lt;/p&gt;

&lt;p&gt;Рассмотрим и разберем более сложные примеры, чтобы лучше понять принцип действия.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Задача 1&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Done&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Первый then возвращает значение 10.&lt;/li&gt;
&lt;li&gt;Второй then возвращает значение 13.&lt;/li&gt;
&lt;li&gt;Третий then возвращает ошибку, которая переходит в catch.&lt;/li&gt;
&lt;li&gt;В методе catch возвращается значение 13, так как метод закончился без ошибки, то переходит дальше к then.&lt;/li&gt;
&lt;li&gt;Выводится значение 13&lt;/li&gt;
&lt;li&gt;Выводится 'Done'
Вот как выглядит точный ответ:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;13
Done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Задача 2&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Boom!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cleanup 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Again!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cleanup 2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Good!!!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Как уже говорилось ранее, finally также возвращает Promise, поэтому цепочка продолжается, а конечный результат будет иметь следующий вид:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cleanup 1
Boom!
Cleanup 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Мы не попадаем в последний catch, так как метод перед ним закончился успешно.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Задача 3&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Catch 1:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Finally 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;C&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Then 1:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;D&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Catch 2:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;E&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Finally 2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;F&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Then 2:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Вспомним, что метод finally не возвращает никакие значения, поэтому данные строки можно убрать, при этом в then попадает значение из предыдущих методов then или catch&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Думаю, что после пояснения результат стал вполне ожидаемым:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Catch 1: A
Finally 1
Then 1: B
Catch 2: D
Finally 2
Then 2: E
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;А вот с ошибками результат будет другой, рассмотрим такой пример:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;First Error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Catch 1:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//First Error&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Success&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Finally 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;//Возникает ошибка, которая обрабатывается в catch&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error in Finally&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//Так как возникла ошибка, то then пропускается&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Then 1:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Catch 2:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//Error in Finally&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Final Recovery&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Then 2:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;//Final Recovery&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Таким образом, finally не возвращает значение, которое может попасть в then, но при этом, может вызвать ошибку, которая в дальнейшем будет обработана.&lt;br&gt;
Конечный результат:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Catch 1: First Error
Finally 1
Catch 2: Error in Finally
Then 2: Final Recovery
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Думаю, на этих примерах принцип действия стал понятнее.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Статические методы класса Promise&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Статические методы предназначены для работы с коллекциями Promises. С их помощью мы можем организовать параллельное выполнение асинхронных операций. Данные методы возвращают новый промис, состояние которых зависит от переданных Promises.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;all() - принимает на вход массив с Promises, а возвращаемый Promise выполняется, когда все Promises из входных данных выполнятся, отклоняется, когда любой из переданных Promise завершается с ошибкой, при этом причина отклонения поступает с первого Promise, который неудачно завершился.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Рассмотрим два примера:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promiseFirst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)]);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promiseFirst&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Данный пример вернет следующий результат:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Promise { &amp;lt;state&amp;gt;: "fulfilled", &amp;lt;value&amp;gt;: Array[4]}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;То есть, все Promises, которые передавались во входные параметры закончились успешно, поэтому конечный Promise закончился с успехом и мы может увидеть результаты каждого выполненного Promise.&lt;/p&gt;

&lt;p&gt;Теперь рассмотрим следующую ситуацию:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promiseSecond&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bad 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bad 2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)]);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;promiseSecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Данный пример вернет следующий результат:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Promise { &amp;lt;state&amp;gt;: "rejected", &amp;lt;reason&amp;gt;: Error: bad 1 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;В нашем случае сразу два Promise закончились с ошибкой, поэтому общий Promise отклоненный, но при этом в его ошибке хранится информация от первого Promise, который закончился неудачно.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;allSettled() - метод, который принимает на вход массив из Promise и возвращает один, как и в случае с методом all, но их отличие в том, что он ждем выполнения всех Promises, неважно, успешны они или нет. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;_Метод allSettled() никогда не отклоняется _&lt;/p&gt;

&lt;p&gt;Данный метод возвращает массив объектов, который имеет следующий вид:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   status // "fulfilled" или "rejected"
   value? // Значение, когда status = "fulfilled", хранит данные по успешной операции
   reason? // Значение, когда status = "rejected", хранит данные по ошибке
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;any() - метод, который принимает массив Promises, как и два предыдущих метода, но выполняется тогда, когда выполняется &lt;strong&gt;любой&lt;/strong&gt; из входных Promises с первым значением выполнения, а отклоняется, когда отклоняются все входные Promises, при этом метод возвращает AggregateError ошибку с массивом причин отклонения. То есть, можно сказать, что метод any - это организатор гонок, в которых либо один победитель, либо все проигравшие.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Рассмотрим пример выполнения данного метода, который заканчивается неудачей:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;any&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bad 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bad 2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bad 3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Успех! Result:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ошибка! Error name:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// AggregateError&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ошибка! Error errors:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Массив ошибок&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Результат будет иметь следующий вид:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ошибка! Error name: AggregateError
Ошибка! Error errors: [ 'bad 1', 'bad 2', 'bad 3' ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;race() - метод, который также принимает массив в качестве входных параметров, а то, разрешается он или отклоняется, зависит от первого завершённого Promise. То есть race - это, как и any тоже своего рода организатор гонок, только победителем может быть как успешно завершенный Promise, так и отклоненный с ошибкой.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;reject() - метод, который возвращает отклоненный Promise по указанной причине. Мы уже использовали его ранее.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;resolve() - метод, который возвращает успешный Promise с указанным значением.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;try() - метод, чтобы была возможность запустить функцию, которая может быть как синхронной, так и асинхронной, и вернуть Promise. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Если callback функция выполняется синхронно и возвращает значение, то данный метод возвращает успешный Promise с этим значением, который потом можно обработать в then().&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Если callback функция выполняется синхронно и возвращает ошибку, то данный метод возвращает отклоненный Promise с этой ошибкой, который потом можно обработать в catch().&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Если callback функция возвращает другой Promise, то данный метод вернет этот Promise.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Рассмотрим пример:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;То есть метод try() - это универсальный контейнер, если мы в него что-то положим, то он обязательно вернет Promise, который в дальнейшем можно обработать с помощью then() или catch().&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;withResolvers() - метод, который позволяет создать Promise и тут же получить функции для управления им. Это может понадобиться, например, когда решение Promise должно быть принято позже или же в другом месте.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Из метода withResolvers() мы можем получить следующие данные:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;promise - созданный Promise&lt;/li&gt;
&lt;li&gt;resolve - функция для успешного завершения Promise&lt;/li&gt;
&lt;li&gt;reject - функция для завершения Promise с ошибкой&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Рассмотрим пример:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withResolvers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Успех!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Успех!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Связь с async/await&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Ключевые слова async и await не являются полноправной заменой Promise, это так называемый синтаксический сахар, для того, чтобы упростить работу с Promise и сделать код более удобочитаемым. Данный синтаксис позволяет писать асинхронный код, который выглядит как синхронный, при этом нет потери производительности и не блокируется основной поток.&lt;/p&gt;

&lt;p&gt;Под капотом async/await работает на основе Promise, а также функций генераторов.&lt;/p&gt;

&lt;p&gt;Если перед функцией поставить ключевое слово async, то данная функция автоматически будет возвращать Promise.&lt;/p&gt;

&lt;p&gt;Рассмотрим пример:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// 42&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;При этом, данную функцию можно записать и через Promise, эквивалентное решение будет выглядеть следующим образом:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ключевое слово await можно использовать только внутри функции, перед которой стоит async, то есть внутри async-функции. Оно заставляет интерпретатор приостановить выполнении функции до тех пор, пока Promise не будет завершен.&lt;/p&gt;

&lt;p&gt;Алгоритм работы:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Если Promise завершился с успехом, то await возвращает его результат.&lt;/li&gt;
&lt;li&gt;Если Promise завершается с ошибкой, то await генерирует ошибку, которую можно обработать через try/catch.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Рассмотрим пример:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fetchDataNew&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Необходимо грамотно подходить к выбору того, что лучше использовать, например, когда нам необходимо выполнить несколько операций параллельно, то лучше использовать Promise, а когда логика требует выполнения последовательных действий, то лучше использовать async/await.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Заключение&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Promise - это фундаментальная блок асинхронного кода, который позволил разработчикам уйти от callback hell и сделать код более предсказуемым, удобочитаемым и элегантным. &lt;/p&gt;

&lt;p&gt;На первый взгляд концепция Promise выглядит сложно, но изучение данной технологии дает большой толчок при работе с современными фреймворками, библиотеками и API.&lt;/p&gt;

&lt;p&gt;Теперь спокойно можно покорять вершины асинхронности, самое главное не прибегать к callback hell :)&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>frontend</category>
      <category>interview</category>
    </item>
    <item>
      <title>HTTP-методы: GET, POST, PUT, DELETE и другие — полный гид</title>
      <dc:creator>Anna</dc:creator>
      <pubDate>Wed, 16 Jul 2025 20:27:36 +0000</pubDate>
      <link>https://forem.com/ukraintseva/http-mietody-get-post-put-delete-i-drughiie-polnyi-ghid-2km3</link>
      <guid>https://forem.com/ukraintseva/http-mietody-get-post-put-delete-i-drughiie-polnyi-ghid-2km3</guid>
      <description>&lt;p&gt;В первую очередь стоит начать с того, а что же такое HTTP.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;HTTP (Hypertext Transfer Protocol)&lt;/strong&gt; - это протокол прикладного уровня, который определяет правила обмена данными между клиентом и сервером.&lt;/p&gt;

&lt;p&gt;В свою очередь HTTP методы - это команды посредством которых клиент взаимодействует с сервером по протоколу HTTP, именно методы определяют, тип операции, которую хочет совершить клиент, например: получение, добавление, удаление данных и тд.&lt;/p&gt;

&lt;p&gt;Методы разделяются по своим свойствам. Бывают следующие виды методов:&lt;/p&gt;

&lt;p&gt;1) Безопасные - это методы, которые не изменяют состояние сервера, то есть методы, которые используются только для чтения и не имеют side effects. К таким методам относятся: GET, HEAD, OPTION, в дальнейшем рассмотрим все эти методы подробнее.&lt;/p&gt;

&lt;p&gt;2) Идемпотентные - это методы, которые не имеют никаких побочных эффектов(side-effects). Иными словами, идемпотентные методы - это методы, которые при повторном идентичном запросе не изменяют состояние сервера. Как пример, рассмотрим случай добавления сущности на сервер, у нас есть два варианта решения этой задачи:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Добавление сущности, когда сервер самостоятельно выбирает новый идентификационный номер ресура.(POST)&lt;/li&gt;
&lt;li&gt;Добавление сущности, когда клиент задает идентификационный номер ресурса.(PUT)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Если рассматривать эти два варианта, то второй метод будет считаться идемпотентным, так как мы вносим изменения в один и тот же ресурс на сервере и при многократном воспроизведении запроса данные на сервере не будут меняться. А что же с первым вариантом? Каждый раз, когда мы будем отправлять запрос сервер будет создавать новую сущность, как раз из-за этого первый вариант и не будет считаться идемпотентным.&lt;/p&gt;

&lt;p&gt;Исходя из описания идемпотентного свойства можно сделать следующий вывод:&lt;br&gt;
 &lt;em&gt;&lt;strong&gt;Все безопасные методы являются идемпотентными, но не все идемпотентные являются безопасными&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;3) Кэшируемые - это методы ответы которого могут быть закэшированы, то есть сохранены для дальнейшего использования, тем  самым снижая кол-во запросов к серверу и увеличению пропускной способности.&lt;br&gt;
Кэшируемые методы имеют следующие ограничения:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Методы GET и HEAD могут быть закэшированы, методы POST и PATCH могут закэшированы, если указаны признак "свежести" (заголовок Expires, который указывает дату и время, по истечении которых кэш должен считаться устаревшим), а также установлен заголовок Content-Location. Другие методы считаются некэшируемыми.&lt;/li&gt;
&lt;li&gt;Коды ответов, которые приходят с сервера, известны как кэшируемые: 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501.&lt;/li&gt;
&lt;li&gt;HTTP заголовок Cache-Control не ограничивает кэширование.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Некоторые запросы, которые не являются кэшированными могут инвалидировать закэшированные данные, в случае, если запрос проходит по одному и тому же URI.&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
Например, мы сохранили данные с помощью метода GET, а далее совершили PUT запрос по тому же URI, тогда ответ от некэшируемого запроса сделает недействительным предыдущий закэшированный ответ, полученный от GET.&lt;/p&gt;

&lt;p&gt;Настало время перейти к самим методам.&lt;/p&gt;

&lt;p&gt;-GET - метод, который запрашивает ресурс с сервера, то есть извлекает данные с сервера для чтения.&lt;br&gt;
Данный метод является безопасным, идемпотентным и кэшируемым. При этом в данном методе есть тело ответа и можно написать тело запроса, но этого лучше не делать по следующим причинам:&lt;br&gt;
а) Сам метод GET подразумевает под собой операцию чтение, а передача тела запроса нарушает семантику, так как тело запроса необходимо дополнительно обрабатывать на сервере.&lt;br&gt;
б) Многие сервера могут игнорировать или даже отклонять тела запросов в методе GET, что может привести к некорректному вызову метода.&lt;br&gt;
в) Возможность возникновения проблем с кэшированием, так как кэши не будут учитывать тело запроса, поэтому при одинаковом URI, но разных телах запроса данные, приходящие с сервера, могут отличаться, тем самым, закэшированные данные могут быть неверные.&lt;br&gt;
г) Проблемы с безопасностью, поскольку тело запроса в методе GET является специфической, то могут возникнуть такие проблемы, как утечка данных или же CSRF атаки и др.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;HEAD - метод, который запрашивает ресурс также, как и метод GET, но без тела ответа. Мы можем использовать данный метод, например, для того, чтобы проверить загрузку большого объема данных, для увеличения пропускной способности.&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Метод HEAD может сделать кэширование метода GET по тому же URI недействительным, когда результат запроса HEAD будет показывать, что закэшированные данные устарели&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;POST - метод для отправки данных на сервер, часто вызывает изменения состояния сервера или side effects. Мы можем использовать данный метод, например, для того, чтобы создавать новые сущности на сервере. Иногда данный метод используется для получения данных, например, когда нам необходимо получить отфильтрованные данные, а размера URI не хватает, чтобы передать все фильтры корректно, а как мы говорили выше, то в методе GET нежелательно использовать тело запроса, и тут на помощь приходит метод POST, в который мы можем передать тело запроса и корректно получить данные, ну и конечно не стоит забывать про то, что метод GET лучше не использовать для передачи чувствительных данных(уж очень легко украсть).&lt;br&gt;
Метод POST не является безопасным и идемпотентным, но он может быть кэшируемым, если будет соблюдено 1 условие для кэшируемых методов.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PUT - метод, который используется для обновления или создания ресурса. Данный метод создает новое или заменяет старое представление ресурса данными, которые приходят в теле запроса.&lt;br&gt;
Разница между PUT и POST заключается в том, что чаще всего PUT используется для редактирования ресурса, в то время, как метод POST отвечает за создание ресурса, именно такое поведение методов является семантически верным. Кроме этого разница этих методов еще и в том, что метод PUT является идемпотентным, а метод POST идемпотентным не является, пример именно с этими методами приведен выше, при пояснении идемпотентности. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PATCH - метод, который используется для частичного редактирования ресурса. Как мы говорили выше, метод PUT также отвечает за изменение данных на сервере, так в чем же разница между методами PUT и PATCH? А разница заключается в том, что метод PUT полностью заменяет ресурс данными, представленными в теле запроса, в то время, как метод PATCH может заменить какие-то конкретные поля у данного ресурса. &lt;br&gt;
Метод PATCH может быть идемпотентным при правильном использовании, а также может быть кэшируемым, но никогда не будет безопасным.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DELETE - метод, который отвечает за удаление данных с сервера. Данный метод не является безопасным и кэшируемым, но является идемпотентным. Например, мы не можем удалить один и тот же ресурс с одинаковым идентификатором дважды.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Настало время приступить к менее известным методам. Итак, приступим.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;OPTION - метод, который запрашивает информацию о возможностях и параметрах доступных методов на конкретном ресурсе. Если говорить проще, то метод OPTION задает следующий вопрос: "Что я могу делать с этим ресурсом?". Данный метод может дать информацию о том, какие методы применимы к ресурсы, какие заголовки можно передавать и тд. В случае, если в URI написана *, то данный запрос применяется ко всему методу. &lt;br&gt;
Данный метод является безопасным и идемпотентным, но не является кэшируемым.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CONNECT - метод, используемый для создания "тунеля" к серверу. Данный процесс можно описать следующим образом: отправляется запрос на создания соединения в котором указывается хост и порт, в случае, если прокси сервер одобряет соединение, то устанавливается связь с конечной точкой, после этого все соединение происходит через прокси.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TRACE - метод, который используется для диагностики и отладки. Принцип работы данного метода заключается в том, что отправляется запрос, а в ответ от сервера приходит тот же запрос, который мы отправили. Зачем это нужно? Например, нам необходимо понять, верно ли мы отправляем запрос, все  заголовки к нему и тд. Также данный метод иногда используется для мониторинга и ведения логов, но данный метод используется редко, так как это может привести к проблемам с безопасностью, например, злоумышленник может украсть важные данные, например, куки, токены и тд. К слову данный метод является идемпотентным, но не является безопасным и кэшируемым.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Итого, мы разобрали все методы. Какие методы мы делаем?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GET - скромный наблюдатель, может читать, но не может записывать.&lt;/li&gt;
&lt;li&gt;POST - создатель, даст данные, а там уже пусть что-то создастся.&lt;/li&gt;
&lt;li&gt;DELETE - ликвидатор, безвозвратное удаление, никак иначе.&lt;/li&gt;
&lt;li&gt;PUT - перфекционист, знает как должен выглядеть ресурс, если его нет, то нужно создать, а если есть, то нужно отредактировать.&lt;/li&gt;
&lt;li&gt;PATCH - хирург, точные изменения, никак иначе&lt;/li&gt;
&lt;li&gt;HEAD - это GET-запрос, который стесняется тела ответа.&lt;/li&gt;
&lt;li&gt;OPTION - как гид в ресторане: расскажет, какие "блюда" доступны для ресурса, но сам ничего не подаст.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Выбирайте методы с умом, и пусть ваш API никогда не узнает, что такое 500 ошибка!&lt;/p&gt;

</description>
      <category>html</category>
      <category>http</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
