> For the complete documentation index, see [llms.txt](https://strctr.gitbook.io/programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://strctr.gitbook.io/programming/01-languages/javascript/01-language/e-controls/e4-promises/02-promise-lifecycle.md).

# 02. Promise State

A promise must be in one of three mutually exclusive states: pending, fulfilled, or rejected.

* **Pending** - результат асинхронного вычисления еще не готов;
* **Fulfilled** - результат вычисления выполнился успешно;
* **Rejected** - во время вычислений возникла ошибка.

![alt text](https://1356653101-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M5bu9Zoywb01ca-XJjd%2F-M5buJXbyydR9RxqeVRI%2F-M5buOpUoMC_WOQeRPi1%2Fpromise_states_simple.jpg?generation=1587660053482408\&alt=media)

**When pending**, a promise:

* may transition to either the fulfilled or rejected state.

**When fulfilled**, a promise:

* must not transition to any other state.
* must have a value, which must not change.

**When rejected**, a promise:

* must not transition to any other state.
* must have a reason, which must not change.

Promise является **установленным** (*settled*) если ассоциированное с Promise вычисление завершилось каким-либо образом. Установленный Promise представляет собой либо успешно вычисленный результат, либо исключение произошедшее при его вычислении.

* Установка Promise выполняется один раз и после чего Promise хранит вычисленный результат.
* Любая последующая установка Promise не будет иметь результата.

Promise позволяет реагировать на изменения его состояния путем установки обработчиков событий двух типов:

* `onFulfilled` – срабатывают, когда `promise` в состоянии «выполнен успешно».
* `onRejected` – срабатывают, когда `promise` в состоянии «выполнен с ошибкой».

Тогда, более формально:

* A promise is fulfilled if `promise.then(f)` will call `f` "as soon as possible."
* A promise is rejected if `promise.then(undefined, r)` will call `r` "as soon as possible."
* A promise is pending if it is neither fulfilled nor rejected.

![](https://1356653101-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M5bu9Zoywb01ca-XJjd%2F-M5buJXbyydR9RxqeVRI%2F-M5buOpWDH2IQ8RRUGNG%2Fpromise-lifecycle.png?generation=1587660054034231\&alt=media)

Общие правила:

* В настоящее время Promise нельзя отменить, а так же нельзя узнать его текущий статус и глубину вложения.
* Rejections Should Be Errors.
* Rejections Should Be Used for Exceptional Situations
* Promise-Returning Functions Should Never Throw
* [States and Fates](https://github.com/domenic/promises-unwrapping/blob/master/docs/states-and-fates.md)

## Promise state chaining

Если результатом Promise-а `P` является другой Promise `T`, то тогда Promise `P` в качестве собственного состояния будет использовать состояние из Promise `T`. Этот подход позволяет объединять Promise в цепочки отслеживая выполнилась или нет вся цепочка Promise.

## Check Promise state

К сожалению, невозможно проверить состояние Promise вызвав какую-то функцию типа `isResolved()` или `isRejected()`. Состояние Promise определяется только тем путем через который пошел control flow выполнения его обработчиков.&#x20;

Невозможно узнать успешно ли был выполнен promise без вызова `then()`, как и невозможно узнать об ошибке без вызова `catch()`. Таким образом, не существует синхронного способа узнать о выполнении асинхронной операции.

Можно реализовать следующую проверку:

```javascript
function withStateChecks(promise) {
  // Don't create a wrapper for promises that can already be queried.
  if (promise.isResolved) return promise;

  let isResolved = false;
  let isRejected = false;

  // Observe the promise, saving the fulfillment in a closure scope.
  const result = promise.then(
    v => {
      isResolved = true;
      return v;
    },
    function(e) {
      isRejected = true;
      throw e;
    }
  );

  result.isFulfilled = () => {
    return isResolved || isRejected;
  };
  result.isResolved = () => {
    return isResolved;
  };
  result.isRejected = () => {
    return isRejected;
  };
  return result;
}
```
