Promise

Promise is a solution to asynchronous programming.

Promise objects have the following two characteristics:

  1. The status of an object is not affected. The Promise object represents an asynchronous operation with three states: Pending, depressing, and Rejected. Only the result of an asynchronous operation can determine which state is currently in, and no other operation can change that state.
  2. Once the state changes it will never change again, and you can get this result at any time. There are only two possibilities for the state of a Promise object to change: from Pending to depressing and from Pending to Rejected. As soon as these two things happen the state is fixed and it won’t change, it will just stay the same and that’s called Resolved.

Basic usage

Var promise = new promise (function(resolve, reject) {
    ... 
    ifResolve (data); }else {
        reject(err)
    }
)
Copy the code

The Promise constructor takes a function as an argument, resolve and reject. They are two functions that are provided by the JavaScript engine and do not need to be deployed themselves.

  • Resolve (‘ Resolved ‘, ‘Resolved’, ‘Resolved’); resolve (‘ Resolved ‘, ‘Resolved’, ‘Resolved’);
  • Reject (reject) is called Pending–>Rejected and passes the error from the asynchronous operation as a parameter.

After the Promise instance is generated, you can use the THEN method to specify the Resolved and Rejected state callback functions, respectively.

promise.then(function(value)  {
    // success
}, function(err){
    // failure
})
Copy the code

The then method can take two callback functions as arguments. Success callback and failure callback, where the second function is optional and does not have to be provided. Both of these functions accept as arguments a value passed from the Promise object.

Note that:

  • Promise will be executed immediately after it’s created,
  • The callback function specified by the THEN method is executed after a step

Write a Promise:

The use of promises can be divided into two parts: creating a new instance and then methods that invoke the instance. So we can also implement these two parts separately:

  • Implement the Promise constructor
  • Implement then methods
Implement the Promise constructor

Let’s start with the constructor and implement the Promise constructor as described above.

The Promise constructor takes a function as an argument, resolve and reject. Their function is to change state from Pending to depressing or Rejected

function Promise (executor) {
    this.state = 'pending';
    this.data = undefined;
    this.reason= undefined;
    this.fn1Callbacks=[];
    this.fn2Callbacks=[];
    let resolve = value => {
        if(this.state === 'pending'){
            this.state = 'fulfilled';
            this.data = value;
            for(leti = 0; i<this.fn1Callbacks.length; i++){ self.fn1Callbacks[i](value); }}};let reject = reason => {
        if(this.state === 'pending'){
            this.state = 'rejected';
            this.reason = reason;
            for (leti = 0; i < self.fn2Callback.length; i++) { self.fn2Callback[i](reason); }}}; try { executor(resolve, reject); } catch (err) { reject(err); }}Copy the code
Implement then methods

The THEN method is called when the state of a Promise changes, whether it succeeds or fails.

Promise instances have THEN methods, which are defined on the prototype object Promise.Prototype. Its job is to add a state change callback to the Promise instance and execute it when the asynchrony completes.

The then method returns a new Promise instance (note, not the original Promise instance). So you can write it chained, where a then method is followed by another THEN method.

Based on the above discussion, we may easily draw the conclusion that…

  • The THEN method can be called on the instance. So the implementation of the THEN method is on top of the Promise prototype.
  • His job is to add a state change callback to the Promise instance and execute it when the asynchrony completes
  • The then method returns a Promise, and a new Promise(detail) object.

Let’s look at the promise implementation

// thenMethod takes two arguments, fn1 and fn2, which are the callback promise.prototype. then = after a Promise succeeds or fails, respectivelyfunction(fn1, fn2) {var self = this var promise2 fn1 = typeof fn1 ==='function' ? fn1 : function(v) {}
  fn2 = typeof fn2 === 'function' ? fn2 : function(r) {}

  if (self.status === 'resolved') {
    return promise2 = new Promise(function(resolve, reject) {
        //todo
    })
  }

  if (self.status === 'rejected') {
    return promise2 = new Promise(function(resolve, reject) {
       //todo
    })
  }

  if (self.status === 'pending') {
    return promise2 = new Promise(function(resolve, reject) {
       // todo
    })
  }
}
Copy the code

The first step is to type the successful callback and failed callback of the input, identify it as a function, and then execute it. The next step is to deal with the three possible states that may exist in the Promise. We divide it into three if blocks, each of which returns a new Promise.

So, the next logical step is:

  • If the Promise state is Resolved, fn1 needs to be executed.
  • If the promise state is Rejected, fn2 needs to be executed.
  • If the promise state is pending, we can’t decide whether to call fn1 or fn2, so we have to store all the methods in the fn1Callback, fn2Callback array. Wait until the state of the Promise is determined.

Fill the following code with the logic above:

Promise.prototype.then = function(fn1, fn2) {
    var self = this
    var promise2
    fn1 = typeof fn1 === 'function' ? fn1 : function(v) {}
    fn2 = typeof fn2 === 'function' ? fn2 : function(r) {}
    if (self.status === 'resolved') {
        return promise2 = new Promise(function(resolve, reject) {var x = fn1(self.data) // fn1(self.data); There will be a return value injected into resolvethenResolve (x)} catch (e) {reject(e)}})}if (self.status === 'rejected') {
        return promise2 = new Promise(function(resolve, reject) {
            try {
                var x = fn2(self.data)
                reject(x)
            } catch (e) {
                reject(e)
            }
        })
    }
    if (self.status === 'pending') {
        return promise2 = new Promise(function(resolve, reject) {
            this.fn1Callback.push(function(value){
                try {
                    var x = fn1(self.data);
                    resolve(x)
                } catch (e) {
                    reject(e)
                }
            })
            this.fn2Callback.push(function(value) {
                try {
                    var x = fn2(self.data);
                    reject(x)
                } catch (e) {
                    reject(e)
                }
            })
        })
    }
}
Copy the code