In June 2015, ES2015 (ES6) received a lot of attention after its official release. One important thing is that promises are listed as official specifications.
Many libraries have implemented promise-like solutions to asynchronous programming/callback hell, including Bluebird, Angular Q, and jQuery’s Deffered.


For ease of understanding, this article will be divided into three parts, each part implements some of the features of the Promise, and finally, step by step, implements A complete Promise that follows the Promise A+ specification.


Promise A+ According to the specification, a Promise has three states, namely
pending(Default state, waiting),
fulfilled(stands for success)
rejected(stands for failure).


Let’s take a look at how Promise is used and what features it has.

var fn = new Promise(function(resolve, reject) {// Asynchronous operationsetTimeout(function() {        
        resolve('resolve 01'// Since reslove and reject are mutually exclusive, reject does not execute reject() because resolve has already been called.'reject 01')
    }, 500)
})
fn().then(function (data) {
    console.log('Success 1:', data)
    return new Promise(function (resolve, reject) {
        reject('reject 02')})},function (err) {
    console.log('Failure 1:', err)
})
.then(function (data) {
    console.log('Success 2:', data)
}, function (err) {
    console.log('Failure 2:', err)
}).then(function (data) {
    console.log('Success 2:', data)}, function (err) {
    console.log('Failure 2:', err)
})Copy the code

Results:



As you can see, promises typically have these features:

The Promise class has a then method. The then method takes two arguments, a Promise success callback and a Promise failure callback, and the two are mutually exclusive


(2) Promise supports chained calls. The return value of then can be either a Promise or a normal value. If it is a normal value, it will be used as the argument to the next successful callback function of then


Promis has other extensions as well


Having said a lot of things, let’s start to implement this thing


= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =

First, the implementation of the Promise class

=> Promise has then methods:

var Promise = function (executor) {
    console.log('Prove not with native Promise')
    var _this = this
    this.status = 'pending'FailVal = undefined // After the operation succeeds or fails, change the status to Succeed or failfunction resolve (val) {
        if ( _this.status === 'pending' ) {
            _this.status = 'resolved'
            _this.successVal = val
        }
    }
    function reject (val) {
        if ( _this.status === 'pending' ) {
            _this.status = 'rejected'_this.failVal = val}} try {// Remember that the Promise argument is a function called an executor. Executor (resolve, reject)} catch (e) {// If an exception occurs, reject(e)}} //thenMethod takes two arguments, the success and failure callback promise.prototype. then =function(ondepressing, onRejected) {var _this = this // This is a big pityif ( _this.status === 'resolved' ) {
        onFulfilled(_this.successVal)
    }
    if ( _this.status === 'rejected' ) {
        onFulfilled(_this.failVal)
    }
}Copy the code
Let’s try it out:

var fn = new Promise(function (resolve, reject) {
    resolve('oooook~')
}) 
fn.then(function (data) {
    console.log('success: ', data)}, function (err) {
    console.log('err: ', err)
})Copy the code

Results:



The results look beautiful. But what about the following?

var fn = new Promise(function (resolve, reject) {
    setTimeout(function () {
        resolve('oooook~')
    }, 500)
}) 
fn.then(function (data) {
    console.log('success: ', data)
}, function (err) {
    console.log('err: ', err)
})Copy the code

Results:



Ok, here’s the problem. Promises aren’t just synchronous calls. After all, with Ajax, the front end is thriving, so we need to make our promises asynchronous.


Modified as follows (the new code is explained in the comments) :

var Promise = function (executor) {
    console.log('that is not in the original Promise of nonsense')
    var _this = this    this.status = 'pending'// By default, This. FailVal = undefined // ----------------- Indicates new code -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- / / callback of success and failure to hold this. OnFulfilledList = [] this. OnRejectedList = []function resolve (val) {
        if ( _this.status === 'pending' ) {
            _this.status = 'resolved'_this. SuccessVal = val / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- to perform all the success callback -- -- -- -- -- -- -- -- -- -- -- -- -- -- --. _this onFulfilledList. ForEach (function(fn){
                fn()
            })
        }
    }
    function reject (val) {
        if ( _this.status === 'pending' ) {
            _this.status = 'rejected'_this. FailVal = val / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- perform all failed callback -- -- -- -- -- -- -- -- -- -- -- -- -- -- --. _this onRejectedList. ForEach (function(fn){
                fn()
            })
        }
    }
    try {
        executor(resolve, reject)
    } catch (e) {
        reject(e)
    }
}
Promise.prototype.then = function (onFulfilled, onRejected) {

    var _this = this

    if ( _this.status === 'resolved' ) {
        onFulfilled(_this.successVal)
    }
    if ( _this.status === 'rejected') {onFulfilled (_this failVal)} / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- for the processing of an asynchronous call -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- / / note: if an asynchronous call, go tothenMethod is still pending, so you need to go back to the executor method, which will execute the list of callback methods (publish-subscribe processing).if ( _this.status === 'pending' ) {
        _this.onFulfilledList.push(function () {
            onFulfilled(_this.successVal)
        })
        _this.onRejectedList.push(function () {
            onRejected(_this.failVal)
        })
    }
}Copy the code

Look at the results:



Currently, asynchrony is supported


I hear you’re all trashing me star-Lord? Star-lord is so cute. Can you bear it




Step by step to implement A Promise A+ standard Promise ii: Promise chain call