Promise Concept (Specification address:Promisesaplus.com/)

A promise represents the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its then method, which registers callbacks to receive either a promise’s eventual value or the reason why the promise cannot be fulfilled.

A Promise represents the final result of an asynchronous operation. The primary way a Promise interacts is through its THEN method, which registers callbacks to receive the result of the Priomse, whether that result is the final value or the reason the Promise cannot be implemented.

Terminology term

“Promise” is an object or function with a then method whose behavior conforms to this specification.

  • A Promise is an object or function that has a THEN method that behaves according to the Promiseg specification

Thenable is an object or function that defines a then method.

  • Thenable is the object or function that defines the THEN method

“Value” is any legal JavaScript value (including undefined, a thenable, or a promise).

  • “Value” is any valid JavaScript value (including undefined, thenable, or promise)

“Exception” is a value that is thrown using the throw statement.

  • An “exception” is an outlier thrown using a throw statement.

“Reason” is a value that indicates why a promise was rejected.

  • “Reason” is a value that indicates the reason the promise was rejected

The Requirements for

Promise States Promise state

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

  • A Promise must be in one of three states: pending, fulfilled or rejected.

When pending, a promise: may transition to either the fulfilled or rejected state.

  • When a Promise is in the pending state, it can be switched to fulfilled or rejected

When fulfilled, a promise:

  1. must not transition to any other state. 2. must have a value, which must not change.
  • When a Promise is fulfilled: do not switch to any other state; There must be a value that cannot be changed.

When rejected, a promise:

  1. must not transition to any other state. 2. must have a reason, which must not change.
  • When a Promise is in the Rejected state: no transition to any other state; There must be a reason that cannot be changed.

The then Method then Method

A promise must provide a then method to access its current or eventual value or reason.

  • A Promise must provide a THEN method to access its current or final value, or the reason it is not implemented

A promise’s then method accept two arguments:

  • The THEN method of a Promise takes two arguments:

    promise.then(onFulfilled, onRejected)

Both onFulfilled and onRejected are optional arguments: 1. If onFulfilled is not a function, it must be ignored. 2. If onRejected is not a function, it must be ignored.

  • This parameter is very depressing and onRejected is optional:
  • If onFulfilled is not a function, it must be ignored;
  • If onRejected is not a function, you must ignore it;

If onFulfilled is a function 1. it must be called after promise is fulfilled, This may be very depressing. This may be very depressing. With promise’s value as its first argument called more than once.

  • If onFulfilled is a function:
  • It must be called after the Promise is complete, with the value of the Promise as its first argument;
  • You cannot call a Promise until it is complete;
  • It cannot be called more than once;

If onRejected is a function 1. it must be called after promise is rejected, With promise’s reason as its first argument. 2. It must not be called before promise is rejected called more than once.

  • If onRejected is a function:
  • You must call a Promise after it has been rejected, with the Promise’s reason as its first argument;
  • You cannot call a Promise until it is complete;
  • It cannot be called more than once;

onFulfilled or onRejected must not be called until the execution context stack contains only platform code. 

  • OnFulfilled or onRejected must not be called until the execution context stack contains only platform code

Here “platform code” means engine, environment, and promise implementation code. In practice, this requirement ensures that onFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack. This can be implemented with either a “macro-task” mechanism such as setTimeout or setImmediate, or with a “micro-task” mechanism such as MutationObserver or process.nextTick. Since the promise implementation is considered platform code, it may itself contain a task-scheduling queue or “trampoline” in which the handlers are called.

  • The “Platform Code” here is the guidance engine, environment, and Promise implementation code. In practice, this requirement ensures that onFulfilled and onRejected execute asynchronously, after calling the then event loop, and using the new stack. This can be accomplished through a “macrotask” mechanism, such as setTimeout or setImmediate, or a “microtask” mechanism, such as MutationObserver or Process.nexttick. Since a Promise implementation is considered platform code, it may itself contain a task scheduling queue or “trampoline” when invoked by an operator.

onFulfilled and onRejected must be called as functions (i.e. with no this value).

  • OnFulfilled and onRejected must be called as functions (that is, without this value)

this value

That is, in strict mode this will be undefined inside of them; in sloppy mode, it will be the global object.

  • In strict mode, this is undefined within them; In non-strict mode, it will be a global object.

then may be called multiple times on the same promise. 1. If/when promise is fulfilled, all respective onFulfilled callbacks must execute in the order of their originating calls to then. 2. If/when promise is rejected, all respective onRejected callbacks must execute in the order of their originating calls to then.

  • Then can be called multiple times on the same promise.
  • If/when a Promise is implemented, all the corresponding onFulfilled callbacks must be executed in the order in which they were originally called to the THEN.
  • If/when a Promise is rejected, all the corresponding onRejected callbacks must be executed in the order in which they were originally called to the THEN.

then must return a promise

promise2 = promise1.then(onFulfilled, onRejected);
Copy the code

1.  If either onFulfilled or onRejected returns a value x, run the Promise Resolution                 Procedure [[Resolve]](promise2, x).

2.  If either onFulfilled or onRejected throws an exception e, promise2 must be                    rejected with e as the reason

3.  If onFulfilled is not a function and promise1 is fulfilled, promise2 must be fulfilled              with the same value as promise1.

4.  If onRejected is not a function and promise1 is rejected, promise2 must be rejected           with the same reason as promise1.

  • The THEN method must return a Promise.
  • If onFulfilled or onRejected returns x, run the Promise Resolution Procedure [[Resolve]](promise2, x).
  • If onFulfilled or onRejected throws an exception e, promise2 must be rejected for e.
  • If onFulfilled is not a function and PromisE1 is implemented, then PromisE2 must be implemented with the same value as PromisE1.
  • If onRejected is not a function and Promise1 is rejected, then Promise2 must be rejected for the same reason as Promise1.

Implementations may allow promise2 === promise1, provided the implementation meets all requirements. Each implementation should document whether it can produce promise2 === promise1 and under what conditions.

  • The implementation may allow PROMISe2 === PromisE1 if all requirements are met. Each implementation should record whether it can produce PROMISe2 === PromisE1 and under what conditions.

The Promise Resolution Procedure Promise Resolution Procedure

The promise resolution procedure is an abstract operation taking as input a promise and a value, which we denote as [[Resolve]](promise, x). If x is a thenable, it attempts to make promise adopt the state of x, under the assumption that x behaves at least somewhat like a promise. Otherwise, it fulfills promise with the value x.

  • The resolution of a Promise is an abstract operation that takes a Promise and value as input, which we represent as [[Resolve]](Promise, x). If x is a thenable, it tries to get the Promise to adopt the state of X, assuming that X behaves at least somewhat like the Promise. Otherwise, it fulfills the promise with the value x.

This treatment of thenables allows promise implementations to interoperate, as long as they expose a Promises/A+-compliant then method. It also allows Promises/A+ implementations to “assimilate” nonconformant implementations with reasonable then methods.

  • This handling of Thenables allows Promises to interoperate as long as they expose A THEN method that complies with Promises/A+. It also allows Promises/A+ implementations to “assimilate” inconsistent implementations with A reasonable then approach.

To run [[Resolve]](promise, x), perform the following steps:

  • To run [[Resolve]](promise, x), do the following:

If promise and x refer to the same object, reject promise with a TypeError as the reason.

  • If the Promise and x reference the same object, the Promise is rejected with TypeError as the reason

If x is a promise, adopt its state:

1. If x is pending, promise must remain pending until x is fulfilled or rejected.

2. If/when x is fulfilled, fulfill promise with the same value.

3. If/when x is rejected, reject promise with the same reason.

  • If X is a Promise, take its state
  • If X is pending, the Promise must remain pending until X is implemented or rejected.
  • If/when x completes, implement the Promise with the same value.
  • If/when X is rejected, reject the Promise for the same reasons.

Generally, it will only be known that x is a true promise if it comes from the current implementation. This clause allows the use of implementation-specific means to adopt the state of known-conformant promises.

  • In general, x is only known to be a true promise if x comes from a current implementation. This clause allows implementation-specific means to adopt a state that is known to conform to a Promise.

Otherwise, if x is an object or function

  • Otherwise, if x is an object or function

If retrieving the property x. hen causes an exception e to be thrown, the Promise is rejected for e. If then is a function, then it is called using x as this, with the first argument being resolvePromise and the second argument being rejectPromise, where: If/when a resolvePromise is called with the value y, run [[Resolve]](promise, y).

Let then be x.then

  • Put then x.t hen

This procedure of first storing a reference to x.then, then testing that reference, and then calling that reference, avoids multiple accesses to the x.then property. Such precautions are important for ensuring consistency in the face of an accessor property, whose value could change between retrievals.

The reference to x.hen is first stored, then tested, and then invoked, avoiding multiple access to the x.hen property. These precautions are important to ensure the consistency of accessor properties, whose values may change between retrieves.

If retrieving the property x.then results in a thrown exception e, reject promise with e as the reason.

  • If retrieving the property x. hen causes an exception e to be thrown, the Promise is rejected for e

If then is a function, call it with x as this, first argument resolvePromise, and second argument rejectPromise, where: 1. If/when resolvePromise is called with a value y, run [[Resolve]](promise, y). 2. If/when rejectPromise is called with a reason r, reject promise with r. 3. If both resolvePromise and rejectPromise are called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored. 4. If calling then throws an exception e, 4.1 If resolvePromise or rejectPromise have been called, ignore it. 4.2 Otherwise, reject promise with eas the reason.

  • If then is a function, then it is called using x as this, with the first argument being resolvePromise and the second argument being rejectPromise, where:
  • If/when a resolvePromise is called with the value y, run [[Resolve]](promise, y).
  • If/when a rejectPromise is called for r reasons, the Promise is rejected with R.
  • If both a resolvePromise and a rejectPromise are called, or if the same argument is called multiple times, the first call takes precedence and any further calls are ignored.
  • If called then an exception E is thrown, and if a resolvePromise or rejectPromise is called, it is ignored. Otherwise, refuse the Promise on the grounds of E.

If then is not a function, fulfill promise with x.

  • If THEN is not a function, then the Promise is implemented with x.

If x is not an object or function, fulfill promise with x.

  • If x is not an object or function, the promise is implemented with X.

If a promise is resolved with a thenable that participates in a circular thenable chain, such that the recursive nature of [[Resolve]](promise, thenable) eventually causes [[Resolve]](promise, thenable) to be called again, following the above algorithm will lead to infinite recursion. Implementations are encouraged, but not required, to detect such recursion and reject promise with an informative TypeError as the reason. 

  • If a Promise is solved with a thenable, the thenable participates in the loop of the thenable chain, The recursive nature of [[Resolve]](promise, thenable) will eventually cause [[Resolve]](promise, thenable) to be called again, which will result in infinite recursion. The implementation encourages, but does not require, detection of this recursion, and rejects promises for useful TypeError messages.

Implementations should not set arbitrary limits on the depth of thenable chains, and assume that beyond that arbitrary limit the recursion will be infinite. Only true cycles should lead to a TypeError; if an infinite chain of distinct thenables is encountered, recursing forever is the correct behavior.

  • The implementation should not set an arbitrary limit on the depth of the Thenable chain, and assume that beyond that arbitrary limit recursion will be infinite. Only true loops will cause TypeError; If an infinite number of different Thenable chains are encountered, then perpetual recursion is the correct behavior.