Write a Promise

Summarize the step-by-step process of implementing promises

1. Implement resolve and reject functions

function Promise(executor){
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    When // // calls resolve, reject directly,this points to the window, so create a variable that holds the this value of the instance object
    const self = this;
    / / 1. Resolve function
    function resolve(data){
        // Change the state of an object (promiseState)
        self.PromiseState = 'fulfilled';
        // Set object result value (promiseResult)
        self.PromiseResult = data;
    }
    / / 2. Reject function
    function reject(data){
        // Change the state of an object (promiseState)
        self.PromiseState = 'rejected'; /// Set object result value (promiseResult)
        self.PromiseResult = data;
    }

    // Call "executor function" synchronously
    executor(resolve, reject);
}

// Add the then method
Promise.prototype.then = function(onResolved, onRejected){}Copy the code

2. Throw an error to change the state

function Promise(executor){
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    const self = this;
    function resolve(data){     
        self.PromiseState = 'fulfilled';
        self.PromiseResult = data;
    }  
    function reject(data){
        self.PromiseState = 'rejected';
        self.PromiseResult = data;
    }
    try{
        // Call "executor function" synchronously
        executor(resolve, reject);
    }catch(e){
        // Change the promise object state to "failed"reject(e); }}Promise.prototype.then = function(onResolved, onRejected){}Copy the code

3. The Promise state can be changed only once

function Promise(executor){
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    const self = this;
    function resolve(data){
        // Determine the status
        if(self.PromiseState ! = ='pending') return;
        self.PromiseState = 'fulfilled';
        self.PromiseResult = data;
    }
    function reject(data){
        // Determine the status
        if(self.PromiseState ! = ='pending') return;
        self.PromiseState = 'rejected';// 
        self.PromiseResult = data;
    }
    try
        executor(resolve, reject);
    }catch(e){ reject(e); }}Promise.prototype.then = function(onResolved, onRejected){}Copy the code

4. The synchronization task then method executes the callback function

function Promise(executor){
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    const self = this;
    function resolve(data){
        if(self.PromiseState ! = ='pending') return;
        self.PromiseState = 'fulfilled';
        self.PromiseResult = data;
    }
    function reject(data){
        if(self.PromiseState ! = ='pending') return;
        self.PromiseState = 'rejected';// 
        self.PromiseResult = data;
    }
    try
        executor(resolve, reject);
    }catch(e){ reject(e); }}// Add the then method
Promise.prototype.then = function(onResolved, onRejected){
    // Call the callback function
    if(this.PromiseState === 'fulfilled'){
        onResolved(this.PromiseResult);
    }
    if(this.PromiseState === 'rejected'){
        onRejected(this.PromiseResult); }}Copy the code

5. The asynchronous task then method performs the callback

function Promise(executor){
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    // Declare attributes
    this.callback = {};
    const self = this;
    function resolve(data){
        if(self.PromiseState ! = ='pending') return;
        self.PromiseState = 'fulfilled';
        self.PromiseResult = data;
        // Call the successful callback function
        if(self.callback.onResolved){ self.callback.onResolved(data); }}function reject(data){ 
        if(self.PromiseState ! = ='pending') return;
        self.PromiseState = 'rejected';// 
        self.PromiseResult = data;
        // Perform the callback
        if(self.callback.onResolved){ self.callback.onResolved(data); }}try{
        executor(resolve, reject);
    }catch(e){ reject(e); }}Promise.prototype.then = function(onResolved, onRejected){
    if(this.PromiseState === 'fulfilled'){
        onResolved(this.PromiseResult);
    }
    if(this.PromiseState === 'rejected'){
        onRejected(this.PromiseResult);
    }
    // Determine pending status
    if(this.PromiseState === 'pending') {// Save the callback function
        this.callback = {
            onResolved: onResolved,
            onRejected: onRejected
        }
    }
}
Copy the code

6. Specify multiple callbacks

function Promise(executor){
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    // Declare attributes
    this.callbacks = [];
    const self = this;
    
    function resolve(data){
        if(self.PromiseState ! = ='pending') return;
        self.PromiseState = 'fulfilled';
        self.PromiseResult = data;
        // Call the successful callback function
        self.callbacks.forEach(item= > {
            item.onResolved(data);
        });
    }
    
    function reject(data){
        if(self.PromiseState ! = ='pending') return;
        self.PromiseState = 'rejected';
        self.PromiseResult = data;
        // Execute the failed callback function
        self.callbacks.forEach(item= > {
            item.onRejected(data);
        });
    }
    try{
        executor(resolve, reject);
    }catch(e){ reject(e); }}Promise.prototype.then = function(onResolved, onRejected){
    if(this.PromiseState === 'fulfilled'){
        onResolved(this.PromiseResult);
    }
    if(this.PromiseState === 'rejected'){
        onRejected(this.PromiseResult);
    }
    // Determine pending status
    if(this.PromiseState === 'pending') {// Save the callback function
        this.callbacks.push({
            onResolved: onResolved,
            onRejected: onRejected }); }}Copy the code

7. Synchronously modify the Promise state then method to return the result

The result of the then method is a Promise object whose state and value depend on the return value and state of the callback function

function Promise(executor){
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    this.callbacks = [];
    const self = this;
 
    function resolve(data){
        if(self.PromiseState ! = ='pending') return;  
        self.PromiseState = 'fulfilled';
        self.PromiseResult = data;
        self.callbacks.forEach(item= > {
            item.onResolved(data);
        });
    }

    function reject(data){
        if(self.PromiseState ! = ='pending') return;  
        self.PromiseState = 'rejected';   
        self.PromiseResult = data;
        self.callbacks.forEach(item= > {
            item.onRejected(data);
        });
    }
    
    try{  
        executor(resolve, reject);
    }catch(e){ reject(e); }}Promise.prototype.then = function(onResolved, onRejected){
    return new Promise((resolve, reject) = > {
        if(this.PromiseState === 'fulfilled') {try{
                // Get the result of executing the callback function
                let result = onResolved(this.PromiseResult);
                // Determine the result type
                if(result instanceof Promise) {//result Is an object of type Promise
                    result.then(v= > {
                        resolve(v);
                    }, r= >{ reject(r); })}else{
                    // Result is not a Promise object
                    // The object status of the result is "success"resolve(result); }}catch(e){ reject(e); }}if(this.PromiseState === 'rejected') {try{
                // Get the result of executing the callback function
                let result = onResolved(this.PromiseResult);
                // Determine the result type
                if(result instanceof Promise) {//result Is an object of type Promise
                    result.then(v= > {
                        resolve(v);
                    }, r= >{ reject(r); })}else{
                    // Result is not a Promise object
                    // The object status of the result is "success"resolve(result); }}catch(e){ reject(e); }}// Determine pending status
        if(this.PromiseState === 'pending') {// Save the callback function
            this.callbacks.push({
                onResolved: onResolved,
                onRejected: onRejected }); }})}Copy the code

8. Asynchronously modify the Promise state then method to return results

function Promise(executor){
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    this.callbacks = [];
    const self = this;
 
    function resolve(data){
        if(self.PromiseState ! = ='pending') return;  
        self.PromiseState = 'fulfilled';
        self.PromiseResult = data;
        self.callbacks.forEach(item= > {
            item.onResolved(data);
        });
    }

    function reject(data){
        if(self.PromiseState ! = ='pending') return;  
        self.PromiseState = 'rejected';   
        self.PromiseResult = data;
        self.callbacks.forEach(item= > {
            item.onRejected(data);
        });
    }
    
    try{  
        executor(resolve, reject);
    }catch(e){ reject(e); }}Promise.prototype.then = function(onResolved, onRejected){
    // Keep the instance object's this
    const self = this;
    return new Promise((resolve, reject) = > {
        if(this.PromiseState === 'fulfilled') {try{
                let result = onResolved(this.PromiseResult);
                if(result instanceof Promise){
                    result.then(v= > {
                        resolve(v);
                    }, r= >{ reject(r); })}else{ resolve(result); }}catch(e){ reject(e); }}if(this.PromiseState === 'rejected') {try{
                // Get the result of executing the callback function
                let result = onResolved(this.PromiseResult);
                // Determine the result type
                if(result instanceof Promise) {//result Is an object of type Promise
                    result.then(v= > {
                        resolve(v);
                    }, r= >{ reject(r); })}else{
                    // Result is not a Promise object
                    // The object status of the result is "success"resolve(result); }}catch(e){ reject(e); }}// Determine pending status
        if(this.PromiseState === 'pending') {// Save the callback function
            this.callbacks.push({
                onResolved: function(){
                    try{
                        // Execute the success callback
                        let result = onResolved(self.PromiseResult);
                        / / determine
                        if(result instanceof Promise){
                            result.then(v= > {
                                resolve(v);
                            }, r= >{ reject(r); })}else{ resolve(result); }}catch(e){ reject(e); }},onRejected: function(){
                    try{
                        // Execute the success callback
                        let result = onRejected(self.PromiseResult);
                        / / determine
                        if(result instanceof Promise){
                            result.then(v= > {
                                resolve(v);
                            }, r= >{ reject(r); })}else{ resolve(result); }}catch(e){ reject(e); }}}); }})}Copy the code

9. Optimize the THEN method

// Add the then method
Promise.prototype.then = function(onResolved, onRejected){
    const self = this;
    return new Promise((resolve, reject) = > {
        // Encapsulate the function
        function callback(type){
            try{
                // Get the result of executing the callback function
                let result = type(self.PromiseResult);
                / / determine
                if(result instanceof Promise) {// If it is an object of type Promise
                    result.then(v= > {
                        resolve(v);
                    }, r= >{ reject(r); })}else{
                    // The object status of the result is "success"resolve(result); }}catch(e){ reject(e); }}Call the callback function PromiseState
        if(this.PromiseState === 'fulfilled'){
            callback(onResolved);
        }
        if(this.PromiseState === 'rejected'){
            callback(onRejected);
        }
        // Determine pending status
        if(this.PromiseState === 'pending') {// Save the callback function
            this.callbacks.push({
                onResolved: function(){
                    callback(onResolved);
                },
                onRejected: function(){ callback(onRejected); }}); }})}Copy the code

10. Catch method and abnormal penetration

// Add the catch method
Promise.prototype.catch = function(onRejected){
    return this.then(undefined, onRejected);
}
Copy the code
// Abnormal penetration
Promise.prototype.then = function(onResolved, onRejected){
    const self = this;
    // Determine the callback parameters
    if(typeofonRejected ! = ='function'){
        onRejected = reason= > {
            throwreason; }}if(typeofonResolved ! = ='function'){
        onResolved = value= > value;
    }
    return new Promise((resolve, reject) = > {
        function callback(type){
            try{
                let result = type(self.PromiseResult);
                if(result instanceof Promise){
                    result.then(v= > {
                        resolve(v);
                    }, r= >{ reject(r); })}else{ resolve(result); }}catch(e){ reject(e); }}if(this.PromiseState === 'fulfilled'){
            callback(onResolved);
        }
        if(this.PromiseState === 'rejected'){
            callback(onRejected);
        }

        if(this.PromiseState === 'pending') {this.callbacks.push({
                onResolved: function(){
                    callback(onResolved);
                },
                onRejected: function(){ callback(onRejected); }}); }})}Copy the code

11. Resolve encapsulation

// Add the resolve method
Promise.resolve = function(value){
    // Return the Promise object
    return new Promise((resolve, reject) = > {
        if(value instanceof Promise){
            value.then(v= >{
                resolve(v);
            }, r= >{ reject(r); })}else{
            // The status is set to successresolve(value); }}); }Copy the code

12. Reject encapsulation

// Add reject
Promise.reject = function(reason){
    return new Promise((resolve, reject) = >{
        reject(reason);
    });
}
Copy the code

13. Encapsulate the all method

// Add the all method
Promise.all = function(promises){
    // Return the result as a Promise object
    return new Promise((resolve, reject) = > {
        // Declare variables
        let count = 0;
        let arr = [];
        / / traverse
        for(let i=0; i<promises.length; i++){ promises[i].then(v= > {
                // The status of the object is success
                // Each promise object succeeds
                count++;
                // Stores the results of the current Promise object's success into an array
                arr[i] = v;
                / / determine
                if(count === promises.length){
                    // Change the statusresolve(arr); }},r= >{ reject(r); }); }}); }Copy the code

14. Race method encapsulation

// Add the race method
Promise.race = function(promises){
    return new Promise((resolve, reject) = > {
        for(let i=0; i<promises.length; i++){ promises[i].then(v= > {
                // Change the status of the returned object to "success"
                resolve(v);
            },r= >{
                // Change the state of the returned object to "failed"reject(r); }}})); }Copy the code

15. Asynchronous execution of callbacks

function Promise(executor){
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    this.callbacks = [];
    const self = this;
   
    function resolve(data){
        if(self.PromiseState ! = ='pending') return;
        self.PromiseState = 'fulfilled';
        self.PromiseResult = data;
        // Call the successful callback function
        setTimeout(() = > {
            self.callbacks.forEach(item= > {
                item.onResolved(data);
            });
        });
    }

    function reject(data){
        if(self.PromiseState ! = ='pending') return;
        self.PromiseState = 'rejected';// 
        self.PromiseResult = data;
        // Failed callback
        setTimeout(() = > {
            self.callbacks.forEach(item= > {
                item.onRejected(data);
            });
        });
    }
    
    try{
        executor(resolve, reject);
    }catch(e){ reject(e); }}Promise.prototype.then = function(onResolved, onRejected){
    const self = this;
    if(typeofonRejected ! = ='function'){
        onRejected = reason= > {
            throwreason; }}if(typeofonResolved ! = ='function'){
        onResolved = value= > value
    }
    return new Promise((resolve, reject) = > {
        function callback(type){
            try{
                let result = type(self.PromiseResult);
                if(result instanceof Promise){
                    result.then(v= > {
                        resolve(v);
                    }, r= >{ reject(r); })}else{ resolve(result); }}catch(e){ reject(e); }}Call the callback function PromiseState
        if(this.PromiseState === 'fulfilled') {setTimeout(() = > {
                callback(onResolved);
            });
        }
        if(this.PromiseState === 'rejected') {setTimeout(() = > {
                callback(onRejected);
            });
        }
        // Determine pending status
        if(this.PromiseState === 'pending') {// Save the callback function
            this.callbacks.push({
                onResolved: function(){
                    callback(onResolved);
                },
                onRejected: function(){ callback(onRejected); }}); }})}Copy the code