Implementing a simple javascript promise with done and then methods

in #programming7 years ago (edited)

I was inspired by the simplicity of the library promise.js (https://github.com/stackp/promisejs/blob/master/promise.js) to dig into its source code and understand how it was implemented. So I went ahead and examined the source code line by line. Here, I want to show you how the then() and done() methods were implemented without going into to much detail about the other methods and functions.

promise.png

The library returns an object that has a property called Promise and which in turn has the constructor function Promise as its value. We will use this constructor function to create the promise instance or object that will be used for our task of resolving a promise (done) and working with the resolved promise (then). For demo purposes I have replaced the name Promise to PromiseMe.

Here is how the instantiation is done:

var promise = new promise.PromiseMe();

The promise object will have access to all the methods in the library.


promise.done(null, 'hey there').then(function(error, response) {
    console.log(response); // 'hey there'
});

Above, we are resolving the message 'hey there' in the done function and effectively printing it in the then method's callback function.

Now, it is time to go into the details of the implementation:

Create an immediately invoked function and assign it to a variable called promise:


var promise = (function() {
}());

Create a constructor function named PromiseMe() inside:


var promise = (function() {
    function PromiseMe() {
    }
     
    return {
       PromiseMe: PromiseMe
   };
}());

Create empty done() and then() methods on the prototype of the prototype of the PromiseMe constructor:


var promise = (function() {
    function PromiseMe() {
    }
    
    PromiseMe.prototype.then = function(callback) {
    };
    
    PromiseMe.prototype.done = function() {
    };

   return {
      PromiseMe: PromiseMe
   };
}());

Implement the done() method:

We expect the done method to take zero or more parameters. Inside the method we use arguments to retrive whatever is passed to it as parameter and assign that to a this.results:


var promise = (function() {
    function PromiseMe() {
    }
    
    PromiseMe.prototype.then = function(callback) {
    };
    
    PromiseMe.prototype.done = function() {
        this._isdone = true;
        this.results = arguments;
        return this;
    };

     return {
        PromiseMe: PromiseMe
    };
}());

Above we created a _isdone propperty on the context and assigined
it the value true.

We also returned this, so that we will be able to do method
chaining (or chain the done method with the then method) as
we were expecting).

Implement the then() method:

The then method takes a callback function with the following form:


 function(error, response) {
 }

Our goal is to ensure that the callback above is called inside our then method and the value we resolved in the done method is passed to it as a response parameter.

Here we use the apply method to invoke the callback and pass to it a null context and an array of parameters (which we
received from the done method's arguments that were assigned to this.results).


var promise = (function() {
    function PromiseMe() {
    }
    
    PromiseMe.prototype.then = function(callback) {
        if(this._isdone) {
          if(typeof callback === 'function') {
            callback.apply(null, this.results);
          }
        }
    };
    
    PromiseMe.prototype.done = function() {
        this._isdone = true;
        this.results = arguments;
        return this;
    };

   return {
       PromiseMe: PromiseMe
   };
}());

After you are done implementing the above, you can test is with the code below:


promise.done(null, 'hey there').then(function(error, response) {
    console.log(response); // 'hey there'
});

Hope this was helpful.

Sort:  

@minnowpond1 has voted on behalf of @minnowpond. If you would like to recieve upvotes from minnowpond on all your posts, simply FOLLOW @minnowpond. To be Resteemed to 4k+ followers and upvoted heavier send 0.25SBD to @minnowpond with your posts url as the memo

Coin Marketplace

STEEM 0.21
TRX 0.13
JST 0.030
BTC 68156.06
ETH 3517.56
USDT 1.00
SBD 2.81