Handwritten Promise function

Posted by natgopal on Tue, 04 Jan 2022 18:31:01 +0100

Handwritten Promise

1 define the overall structure

class Promise{
    /*
    Promise Constructor
    executor:  Internally synchronously executed functions (resolve, reject) = > {}
     */
   	constructor(executor){

    }

    /*
    Specify the success / failure callback function for promise
    The return value of the function is a new promise object
     */
 	then(onResolved, onRejected){

    }

    /*
    Specify the failed callback function for promise
    Is the syntax of then(null, onRejected)
     */
    catch(onRejected){

    }

    /*
    Returns a promise object with a success value specified
     */
    Promise.resolve = function (value){

    }

    /*
    Returns a promise object specifying the failure reason
     */
    static reject(reason){

    }

    /*
    all Implementation of the method: return a promise. Only when all the promises in the promises are successful will it succeed finally. As long as there is a failure, it will fail directly
     */
    static all(promises){
        
    }
    
    /*
    race Method implementation: once a promise is resolved or rejected, the returned promise will be the current state. Whoever changes the state first will return to who
     */
    static race(promises){
        
    }
    
}

2 implementation of promise constructor

constructor(executor){
    //Add attribute
    this.PromiseState = 'pending';
    this.PromiseResult = null;
    //Declare properties
    this.callbacks = [];
    //Save the value of this of the instance object
    const self = this;// self _this that
    //resolve function
    function resolve(data){
        //Judgment state
        if(self.PromiseState !== 'pending') return;
        //1. Modify the object's state (promiseState)
        self.PromiseState = 'fulfilled';// resolved
        //2. Set the object result value (promiseResult)
        self.PromiseResult = data;
        //Call successful callback function
        setTimeout(() => {
            self.callbacks.forEach(item => {
                item.onResolved(data);
            });
        });
    }
    //reject function
    function reject(data){
        //Judgment state
        if(self.PromiseState !== 'pending') return;
        //1. Modify the object's state (promiseState)
        self.PromiseState = 'rejected';//
        //2. Set the object result value (promiseResult)
        self.PromiseResult = data;
        //Failed callback execution
        setTimeout(() => {
            self.callbacks.forEach(item => {
                item.onRejected(data);
            });
        });
    }
    try{
        //Synchronously call "actuator function"
        executor(resolve, reject);
    }catch(e){
        //Modify the promise object status to fail
        reject(e);
    }
}

3 promise. Implementation of then() / catch()

//then method encapsulation
then(onResolved,onRejected){
    const self = this;
    //Determine callback function parameters
    if(typeof onRejected !== 'function'){
        onRejected = reason => {
            throw reason;
        }
    }
    if(typeof onResolved !== 'function'){
        onResolved = value => value;
        //value => { return value};
    }
    return new Promise((resolve, reject) => {
        //Encapsulation function
        function callback(type){
            try{
                //Get the execution result of the callback function
                let result = type(self.PromiseResult);
                //judge
                if(result instanceof Promise){
                    //If it is an object of Promise type
                    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'){
            setTimeout(() => {
                callback(onResolved);
            });
        }
        if(this.PromiseState === 'rejected'){
            setTimeout(() => {
                callback(onRejected);
            });
        }
        //Determine pending status
        if(this.PromiseState === 'pending'){
            //Save callback function
            this.callbacks.push({
                onResolved: function(){
                    callback(onResolved);
                },
                onRejected: function(){
                    callback(onRejected);
                }
            });
        }
    })
}

//catch method
catch(onRejected){
    return this.then(undefined, onRejected);
}

4 Promise. Implementation of resolve() / reject()

//Add resolve method
static resolve(value){
    //Return 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 success
            resolve(value);
        }
    });
}

//Add reject method
static reject(reason){
    return new Promise((resolve, reject)=>{
        reject(reason);
    });
}

5 Promise. Implementation of all / race()

//Add all method
static all(promises){
    //The returned result is promise object
    return new Promise((resolve, reject) => {
        //Declare variable
        let count = 0;
        let arr = [];
        //ergodic
        for(let i=0;i<promises.length;i++){
            //
            promises[i].then(v => {
                //Know that the status of the object is successful
                //Each promise object succeeded
                count++;
                //Store the successful result of the current promise object into the array
                arr[i] = v;
                //judge
                if(count === promises.length){
                    //modify state
                    resolve(arr);
                }
            }, r => {
                reject(r);
            });
        }
    });
}

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

Class 6 encapsulation

class encapsulation: in js classes, there are three methods: constructor construction method, static method and ordinary method.

"constructor construction method"

1. Concept

Class is used to build objects, and the constructor constructor constructor is used to build object instances.

2. Usage

When using the new keyword to generate an object, the constructor method will be executed, and the final return result is the generated object instance.
When a class does not have a constructor method, it will automatically generate an empty constructor method, and the return result is empty.
When instantiating an object with the new keyword, the parameters passed in will be passed in as the parameters of the constructor constructor.

class Point {
    constructor(name) {
        console.log('Instantiate objects:'+ name);
    }
}
new Point('testObj');
//Instantiate objects:testObj

"Common method"

1. Concept

The ordinary method of class can be regarded as another writing method of constructor, which is equivalent to defining the method on the prototype attribute of class.

2. Usage

​ (1). This method is used on the object instantiated by this class

class Point {
    toString() {
        // ...
    }
}

let obj = new Point();
obj.toString();

​ (2). This method is called directly through the prototype of the class

class Point {
    toString() {
        // ...
    }
}

Point.prototype.toString();

​ (3). By subclass__ proto__ call

class Foo {
  commonMethod() {
    return 'hello';
  }
}

class Bar extends Foo {
}

Bar.__proto__.prototype.commonMethod();

"Static method"

1. Concept

Class is equivalent to the prototype of an instance. All methods defined in the class will be inherited by the instance. If you add the static keyword before a method, it means that the method * * will not be inherited by the instance, but will be called directly through the class (calling through the class means calling * * outside the class), which is called "static method".

2. Usage

Static methods can only be called on the current class and cannot be called by the instance object of the class. A static method of a parent class can be inherited by a child class.

Therefore, there are three ways for static methods to be called (all three methods are used in the following code, please read patiently):
- called directly by the parent class
Subclass is called after inheriting the parent class.
- subclasses are called through super objects

class Foo {
  static classMethod() {
    return 'hello';
  }
}

Foo.classMethod();  //hello

class Bar extends Foo {
}

class Cla extends Foo {
    return super.classMethod(); //hello
}

Bar.classMethod();  //hello
contrastStatic methodCommon methodConstruction method
keywordstaticnothingconstructor
Usage scenarioDeclares a method that is used only by the current class or subclasses of the current classCreate methods that can be called directly by instantiated objectsThe method executed when instantiating an object through this class with the new keyword
Use objectCurrent class or subclass of current classAn object generated by instantiation of the class or a subclass of the classThe class itself
Call method1. Direct call of parent class
The 2. subclass calls after inheriting the parent class.
3. Subclasses are called through super objects
1. Object calls generated through instances of this class and its subclasses
2. This class is called through prototype
3. The subclass of this class is passed__ proto__ Implicit prototype chain call
1. Called when this class instantiates an object
2. Subclasses of this class are called with the super keyword

Note: in class, its static attribute and common attribute can have the same name. However, duplicate names are not recommended, and the demo will not be given here

Sample demo

class Person{
    constructor() {
        // Everything added to this will exist on different instances
        this.locate = () => console.log('instance',this);
    }
    
    // Defined on the prototype object of the class
    locate(){
        console.log('prototype', this);
    }
    
    // Defined on the class itself
    static locate(){
        console.log('class',this);
    }
}

let p = new Person();

p.locate();                  // instance, Person()
Person.prototype.locate();   // prototype. {constructor: ... }
Person.locate();             // class, class Person { }

Topics: Front-end