Implementation of simple ES6 promise function (1)

Time:2021-7-1

Promise objects are used for deferred and asynchronous calculations. A promise object represents an operation that has not yet been completed but is expected to be completed in the future.

Let’s start with an example a to get familiar with the grammar

var p = new Promise(function(resolve, reject){
        console.log('1');
        //Run the subsequent callback list, for example: then, when, etc. Otherwise, the functions in then will not be executed
        resolve('go next'); 
    });
    
    //Think only of success
    p.then(function(){
        console.log(2, arguments);
        return 'next';
    }, null).then(function(){
        console.log(3, arguments)
    }, null);
    
    //Output
    1
    2 ['go next']
    3 ['next']

The original idea

Function promise (func) {// takes a function as an argument
    
    }
    
    Promise.prototype = {
    
        Then: function (callback) {// takes a function as an argument
            
            return this; //  Support chain call
        }
    }

For example a, resolve is a function, and it is not passed by the user. All promise should have a resolve method, and this method should be passed to the function in promise constructor as a parameter.

Function promise (func) {// takes a function as an argument
        **func(this.resolve);**
    }
    
    Promise.prototype = {
        
        **resolve: function(){
        
        }**,
        
        Then: function (callback) {// takes a function as an argument
            
            return this; //  Support chain call
        }
    }

Promise executes the callback in order and is triggered by resolve.

Function promise (func) {// takes a function as an argument
        **this.doneList = []; //  Callback list**
        **func(this.resolve.bind(this)); //  Bind this object by the way**
    }
    
    Promise.prototype = {
        
        resolve: function(){
            **//Execution callback list
            while(true){
                if( this.doneList.length === 0 ){
                    break;
                }
                this.doneList.shift().apply(this);
            }**
        },
        
        Then: function (callback) {// takes a function as an argument
            **this.doneList.push(callback); //  Join callback queue**
            return this; //  Support chain call
        }
    }

OK, now write a test case

var p =new Promise(function(resolve){
            console.log('a');
            resolve();
        }).then(function(){
            console.log('b');
        });
        
     //Output
     'a'

What the hell? Print P

    console.log(p);

Implementation of simple ES6 promise function (1)

We found that there is a function in the original donelist that has not been run. Run this function again

p.doneList[0].call(this);
    
    //Results
    console.log('b'); //  Print B

Breaking point tracking, it is found that promise first executes the resolve method, then executes then, and pushes the function to donelist. However, the functions in donelist have never been executed again. What shall I do? We can add a state to promise to describe the current state, which is divided into pending and done. If the state is already completed when then is executed, switch to the unfinished state and execute the resolve method.

Function promise (func) {// takes a function as an argument
        **this.state = 'pending'; //  Initialization status**
        this.doneList = []; //  Callback list
        func(this.resolve.bind(this)); //  Bind this object by the way
    }
    
    Promise.prototype = {
        
        resolve: function(){
            //Execution callback list
            while(true){
                if( this.doneList.length === 0 ){
                    **this.state = 'done'; //  Callback list is empty, change state**
                    break;
                }
                this.doneList.shift().apply(this);
            }
        },
        
        Then: function (callback) {// is also a receiving function
            this.doneList.push(callback); //  Join callback queue
            
            if( this.state === 'done'){
                this.state = 'pneding';
                this.resolve();
            }
            
            return this; //  Support chain call
        }
    }

Test again with an example similar to the one above

    var p =new Promise(function(resolve){
            console.log('a');
            resolve();
        }).then(function(){
            console.log('b');
        }).then(function(){
            console.log('c');
        });

Result screenshot
Implementation of simple ES6 promise function (1)

In this case, our customized promise basic function has completed the most core part. Some may wonder, what the hell are you writing about? The following code is simpler and can achieve the same function

Function promise (func) {// takes a function as an argument
   
        func(this.resolve.bind(this)); //  Bind this object by the way
    }
    
    Promise.prototype = {
        
        resolve: function(){
            //Do nothing    
        },
        
        Then: function (callback) {// is also a receiving function
            callback.call(this); //  Direct operation
            return this; //  Support chain call
        }
    }

test case

    var p =new Promise(function(resolve){
            console.log('d');
            resolve();
        }).then(function(){
            console.log('e');
        }).then(function(){
            console.log('f');
        });

result:
Implementation of simple ES6 promise function (1)

However, the article said at the beginning

Promise objects are used for deferred and asynchronous computation

The callback list is executed in sequence. Final code and test

function Promise(func){
        this.state = 'pending';
        this.doneList = []; 
        func(this.resolve.bind(this)); 
    }

    Promise.prototype = {
        
        resolve: function(){
            while(true){
                if( this.doneList.length === 0 ){
                    this.state = 'done';
                    break;
                }
                this.doneList.shift().apply(this);
            }
        },
        
        then: function(callback){ 
            this.doneList.push(callback); 
            if( this.state === 'done'){
                this.state = 'pending';
                this.resolve();
            }
            return this; 
        }
    }

    var p = new Promise(function(resolve){
            window.setTimeout(function(){
                console.log('d');
                resolve();
            }, 1000);
        }).then(function(){
            console.log('e');
        }).then(function(){
            console.log('f');
        });

    Console.log ('blocked? ');

Output:
Implementation of simple ES6 promise function (1)

Is the first output blocked, After one second, D, e and F are output successively. As you can see, not only does not block the subsequent code execution, but also callbacks are executed in sequence.

end.

The next part continues to improve, such as data transfer and how to handle when the function in then returns a promise. You are welcome to have any questions or suggestions and communicate with us.

Recommended Today

Implementation example of go operation etcd

etcdIt is an open-source, distributed key value pair data storage system, which provides shared configuration, service registration and discovery. This paper mainly introduces the installation and use of etcd. Etcdetcd introduction etcdIt is an open source and highly available distributed key value storage system developed with go language, which can be used to configure sharing […]