es6 ---> Handwritten a promise

A promise example:

var getJSON = function(url) {
    var promise = new Promise(function(resolve, reject) {
        // XHR对象发现ajax请求
        var client = new XMLHttpReqeust();
        client.open("GET", url);
        client.onreadystatechange = handler;
        client.responseType = "json";
        client.setRequestHeader("Accept", "application/json");
        client.send();
         
        function hanlder(){
            if (this.readyState !== 4) {
                return;
            }
            if (this.status === 200) {
                resolve(this.response);
            } else {
                reject(new Error(this.statusText));
            }
        };
    });
    return promise;
}
getJSON("/posts.json").then(function(json) {
    console.log("Content: " + json);
}, function(error) {
    console.error("出错了!', error);
});

When the above call new Promise, the transfer function of a function (resolve, reject), this function is referred to in the specification exector performed.
Therefore, first of all: a need to pass exector actuator :

function Promise(exector) {
    //...
}

Promise determine the effect of the internal exector:
As can be seen in native exector passed two parameters, the first reject and Resolve for success or failure of a second representative.

function Promise(exector) {
    let self = this;
    this.value = undefined;
    this.reason = reason;
    
    // 执行成功
    function resolve(value) {
        self.value = value;
    }
    
    // 执行失败
    function reject(reason) {
        self.reason = reason;
    }
     
    exector(resolve, reject);
}

Add state:
execution promise is not reversible, it is necessary to record a status of its state, initially as padding, succeeded to resolve, it failed to reject

function Promise(exector) {
    let self = this;
    this.status = "padding";
    this.value = value;
    this.reason = reason;
   
    // 成功
    function resolve(value) {
        if(self.status === "padding") {
            self.value = value;
            self.status = "resolved";
        }
    }
     
    // 失败
    function  reject(reason) {
        if(self.status === "padding") {
            self.reason = reason;
            self.status = "reject";
        }
    }
   
    // 对异常的处理
    try {
        exector(resolve, reject);
    } catch(e) {
        reject(e)
    }
}

The method then adding prototype:
note Promise example use is p.then (onFulfilled, onRejected), can then add on the prototype Promise method defined above.

Promise.prototype.then = function(onFulfilled, onRejected) {
    let self = this;
    if(this.status === "resolved") {
        onFulfilled(self.value);
    }
     
    if(this.status === "rejected") {
        onRejected(self.value);
    }
}

2 new array to complete asynchronous operation:
calling Promise prepared above are synchronized, but are generally used asynchronously Promise, so need to be modified to the Promise and the prototype.
If asynchronous, the padding in the state, the callback function fn stored in the array!

function Promise(exector) {
    let self = this;
    this.status = "padding";
    this.value = undefined;
    this.reason = undefined;
    
    // 存储then中成功的回调函数
    this.onResolvedCallbacks = [];
    // 存储then中失败的回调函数
    this.onRejectedCallbacks = [];
   
   // 成功执行
   function resolve(value) {
       if(self.status === "padding") {
           self.value = value;
           self.status = "resolved";
            
           // 成功后遍历then中成功的所有回调函数
           self.onResolvedCallbacks.forEach(fn => fn());
       }
   }
    
   // 失败执行
   function reject(reason) {
       if(self.status === "padding") {
           self.reason = reason;
           self.status = "rejected";
            
           // 失败后遍历then中失败的所有回调函数
           self.onRejectedCallbacks.forEach(fn => fn());
       }
   }
    
   // 对异常进行处理
   try {
       exector(resolve, reject);
   } catch(e) {
       reject(e)
   }
}

// Promise.prototype.then
Promise.prototype.then = function(onFulfilled, onRejected) {
    let self = this;
    
    // 成功
    if (this.status === "rejected") {
        onFulfilled(self.value);
    }
    // 失败
    if (this.status === "resolved") {
        onRejected(self.reason);
    }
    // padding
    if (this.status === "padding") {
        // 推进onResolvedCallbacks数组
        this.onResolvedCallbacks.push( () => {
            onFulfilled(self.value);
        })
        this.onRejectedCallbacks.push( () => {
            onRejected(self.reason);
        })
    }
}

Reference "ES6 Standard Getting Started" (3rd edition) P276
Reference https://www.jianshu.com/p/4b126518c26d

Guess you like

Origin blog.csdn.net/piano9425/article/details/93588173