This is the fourth day of my participation in the August More text Challenge. For details, see:August is more challenging

The introduction to Promise and the use of related methods have been written in the front, the key issues of Promise, and the need for children’s shoes please move on. This article writes down the core principles of Promise:

  1. The constructor for Promise
  2. Initialize data
  3. Implement the resolve method
  4. Implement the Reject method
  5. The executor also needs to return an error message when it throws an exception

The Promise constructor

Promise is defined using the new keyword. It is clear that a promise is a constructor. Thus we can derive the simplest case:

function Promise1() {}
Copy the code

When you use a Promise, you always pass in a method called an executor.

The executable contains two arguments: resolve and reject.

Resolve and Reject are two methods defined in the PROMISE constructor.

function Promise1(executor){
    function resolve() {}
    function reject() {}
    executor(resolve, reject);
}
Copy the code

2. Initialize data

Since the three states of a promise are commonly used, we made the string constants for later use.

var PENDING = "pending";
var FULFILLED = "fulfilled";
var REJECTED = "rejected";
Copy the code

The promise constructor prepares some variables:

  • The status variable stores the state of the promise. The initial state is pending. (This will be fulfilled someday, which will be fulfilled someday.) (This will be fulfilled someday, which will be fulfilled someday.) (This will be fulfilled someday, which will be fulfilled someday.)
  • The data variable is used to store the results returned by the promise;
  • The callbacks variable is used to store two callbacks for the THEN setting, each with the structure {onResolved(){}, onRejected(){}}. The array is used here so that a promise can set multiple success/failure callbacks.
function Promise1(executor){
    var _this = this;
    _this.status = PENDING;
    _this.data = undefined;
    _this.callbacks = [];
}
Copy the code

Implement the resolve method

What does Resolve do internally?

  1. This is very depressing. The state of a promise can only change from pending to fulfilled/rejected. Therefore, judge whether the state is pending first.
  2. This is very depressing.
  3. Save incoming data for later use;
  4. If there is any content in the callbacks, then the onResolved method is executed. Since the callbacks must be executed asynchronously, the setTimeout method is used for asynchronous execution.

Why do you need callbacks to store callbacks?

When the user first specifies the callback function, the state of the promise does not change and the callback function cannot be executed, so save the callback function and call it after the state changes.

  • Callbacks only store the specified callback function when the user first specifies it and then changes the state. This is done in the THEN method.
  • Callbacks do not store data when the user first changes the state and then specifies the callback function;
function reslove(value) {
    if(_this.status ! = PENDING)return;
    _this.status = FULFILLED;
    _this.data = value;
    if (_this.callbacks.length > 0) {
        setTimeout(function() {
            _this.callbacks.forEach(function(callbackObj) { callbackObj.onResolved(value); }); }); }}Copy the code

Implement the Reject method

The internal operations of Reject are close to the same as those of resolve, with different states and callbacks.

  1. This is very depressing. The state of a promise can only change from pending to fulfilled/rejected. Therefore, judge whether the state is pending first.
  2. Change the state to rejected;
  3. Save incoming data for later use;
  4. If there is something in the callbacks, then the onRejected method is executed. Since the callbacks must be executed asynchronously, the setTimeout method is used to implement asynchronous execution.
function reject(reason) {
  if(_this.status ! = PENDING)return;
  _this.status = REJECTED;
  _this.data = reason;
  if (_this.callbacks.length > 0) {
    setTimeout(function() {
      _this.callbacks.forEach(function(callbackObj) { callbackObj.onRejected(reason); }); }); }}Copy the code

The executor also needs to return error information when it throws an exception

Three ways to change the state of a Promise are mentioned in the key issue of Promise:

  • Resolve (value): If the current state is pending, the state will be fulfilled.
  • Reject (reason): Rejected if the current state is pending;
  • Throws an exception: if the current state is pending, it will become rejected.

The executor can make errors during execution, so when an exception is thrown, it needs to catch it and change the promise state to Rejected. So you need to coat the executor with methods to catch exceptions and call the reject method when something goes wrong.

try {
    executor(reslove, reject);
} catch (error) {
    reject(error);
}
Copy the code