Promise in Javascript

mathans1695

mathans1695

Posted on July 9, 2020

Promise in Javascript

I just wanted to share what is promise in javascript?, because I struggled to understand the concept from videos and articles, so I thought of sharing a simple Promise object that I have created. I hope you guys will have better understanding after going through this article.

Prerequisite:

Before getting started, you should have basic understanding of OOJS, callback functions and prototype methods.

Callback Function:

Callback function is a function which are being passed into another function as a reference and got executed there. Have a look at the example below to have a better understanding.

Code

function A(callback) {
    //Call function B
    callback();
}

function B() {
    console.log('Function B got Executed');
}

//Calling the function A with function B as parameter
A(B);

Console

Function B got executed

The above code will output "Function B got executed" in console, since we are passing the reference of function B to function A as parameter. Function B are called back inside the function A. That's why it's called as callback function.

Promises:

Simply, Promises will always come back with a status, no matter what happens.

It's like give me the task, I will definitely tell you whether the task has completed or not in future period. And also it'll give the result or error along with the status.

Let's say you're fetching a resource from a website using your program,

  1. You will make a request to the website,
  2. Website may respond to your request with a success response or an error response.
    • If success means - You will get the desired resource as response.
    • If Error means - You will get an error as response. I have an ultra slow network connection, so I often receive connection timed out as response.

Code

function temp() {
  //Fetch will return a promise
  let promise = fetch('https://jsonplaceholder.typicode.com/users');
  console.log(promise);
}

//Call temp function
temp();

(Don't worry about fetch api right now)

Fetching from Website:
I am using fetch API to make a request to the URL https://jsonplaceholder.typicode.com/users to get users data inside temp function - let promise = fetch('https://jsonplaceholder.typicode.com/users').

  • If success means - fetch will return a Promise object with status: resolved and value: Response object.

    Note: status property of Response object will be status: 200. Success means - You will have the desired resource inside the Response object.

>Promise {<pending>}
  >__proto__: Promise
   [[PromiseStatus]]: "resolved"
  >[[PromiseValue]]: Response
     body: (...)
     bodyUsed: false
    >headers: Headers {}
     ok: true
     redirected: false
     status: 200
     statusText: ""
     type: "cors"
     url: "https://jsonplaceholder.typicode.com/users"
    >__proto__: Response
  • If Error means - fetch will return a Promise object with status: resolved and value: response object.

    Note: status property of Response object will be status: 404. Error means - You will get an error response.

    Here, I used invalid URL https://jsonplaceholder.typicode.com/use, so I am getting 404 status

>Promise {<pending>}
 >__proto__: Promise
  [[PromiseStatus]]: "resolved"
 >[[PromiseValue]]: Response
    body: (...)
    bodyUsed: false
   >headers: Headers {}
    ok: false
    redirected: false
    status: 404
    statusText: ""
    type: "cors"
    url: "https://jsonplaceholder.typicode.com/use"
   >__proto__: Response

Accessing the resource:

  • To access the success Response from Promise object, we have to call then method with the Promise instance - "promise".
  • For accessing error Response, catch method is used to capture the error response.
function temp() {
  //Fetch will return a promise
  let promise = fetch('https://jsonplaceholder.typicode.com/users');

  //accessing the response using then()
  promise.then(function(res) {
    return res.json();
  })
  .then(function(json){
    console.log(json);
  })
}

temp();

Here, We are getting the Response by calling then method on Promise instance - "promise", then method accept an anonymous function as argument.
If you put this line inside temp function - promise.then((res) => {console.log(res)}), you will get the Response object as below:

>Response {type: "cors", url: "https://jsonplaceholder.typicode.com/users", redirected: false, status: 200, ok: true, …}

In first then method, we are returning res.json(), json method will return another Promise object.
If you put this line inside temp function- promise.then((res) => {console.log(res.json())}), you will get a Promise object as below:

>Promise {<pending>}
  >__proto__: Promise
    [[PromiseStatus]]: "resolved"
   >[[PromiseValue]]: Array(10)

Second then method is used again to capture the Response object from Promise object returned from res.json().

 Now, you will get `Array` of 10 users in console as below:
10) [{…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}, {…}]
0: {id: 1, name: "Leanne Graham", username: "Bret", email: "Sincere@april.biz", address: {…}, …}
1: {id: 2, name: "Ervin Howell", username: "Antonette", email: "Shanna@melissa.tv", address: {…}, …}
2: {id: 3, name: "Clementine Bauch", username: "Samantha", email: "Nathan@yesenia.net", address: {…}, …}
3: {id: 4, name: "Patricia Lebsack", username: "Karianne", email: "Julianne.OConner@kory.org", address: {…}, …}
4: {id: 5, name: "Chelsey Dietrich", username: "Kamren", email: "Lucio_Hettinger@annie.ca", address: {…}, …}
5: {id: 6, name: "Mrs. Dennis Schulist", username: "Leopoldo_Corkery", email: "Karley_Dach@jasper.info", address: {…}, …}
6: {id: 7, name: "Kurtis Weissnat", username: "Elwyn.Skiles", email: "Telly.Hoeger@billy.biz", address: {…}, …}
7: {id: 8, name: "Nicholas Runolfsdottir V", username: "Maxime_Nienow", email: "Sherwood@rosamond.me", address: {…}, …}
8: {id: 9, name: "Glenna Reichert", username: "Delphine", email: "Chaim_McDermott@dana.io", address: {…}, …}
9: {id: 10, name: "Clementina DuBuque", username: "Moriah.Stanton", email: "Rey.Padberg@karina.biz", address: {…}, …}
length: 10
__proto__: Array(0)

Using Javascript Promise Object;

Instead of getting the Promise object from Fetch API, we can define our own Promise object:

const promise = new Promise(function(resolve, reject) {
  const success = true;
  if(success) {
    resolve('Content Loaded');
  } else {
    reject('Some error occurred');
  }
});

promise
.then(function(success){
  console.log(success);
})
.catch(function(error) {
  console.log(error);
})

Instantiating Promise Object:
Here, I am instantiating new Promise object and stored it in a variable called promise.

  • The Promise object accept an anonymous function as an argument, the anonymous itself accept two callback functions as arguments.

  • Inside the anonymous function, we are calling the corresponding callback function based on the conditional inside the anonymous function.

    • Conditions:
      • if(success) evaluates to true -> call resolve('Content Loaded') - resolve callback function will be called.
      • else -> call reject('Some error occurred') - reject callback function will be called.
    • Since, the success variable set to true, the if statement will always evaluates to true, so the resolve function will be called.

    Now, the promise variable will have a Promise object with status as "resolved" and response as "Content Loaded" as below:

>Promise {<resolved>: "Content Loaded"}
  >__proto__: Promise
    [[PromiseStatus]]: "resolved"
   >[[PromiseValue]]: "Content Loaded"

Try - console.log(promise), you will get an output like above in console.

Capturing the response:

  • The response can be captured by calling then method on Promise instance - "promise" by passing an anoynmous function with an argument(success) to capture the value "Content Loaded" in variable success.(success will have a string - Content Loaded). ####Output:
Content Loaded
  • Try - changing the success variable inside the Promise object anonymous function to false like const success = false, as a result:
    • else block will be executed during instantiation, which inturn will call the reject callback function, which can be captured using catch method on Promise instance - "promise".

Change success variable: const success = false

Some error occurred

Note: Calling the reject('Some error occurred'), will give us a Promise object - which will have status as "rejected" and value as "Some error occurred":

Reject Promise object:

Promise {<rejected>: "Some error occurred"}
__proto__: Promise
[[PromiseStatus]]: "rejected"
[[PromiseValue]]: "Some error occurred"

Summary of Promise:

  • Promise object has three states(status):

    • resolved - If the request is fullfilled, you will get a Promise object with status "resolved".
    • rejected - If the request is not fullfilled, you will get a Promise object with status "rejected".
    • pending - If the request is in intermediate state, you will get a Promise object with status "pending" and value "undefined". Try:console.log(new Promise(() => {});, you will get a pending response.
  • Response capturing:

    • resolved - The Response object can be captured using then method on Promise instance.
    • rejected - The Response object can be captured using catch method on Promise instance.
    • pending - pending response can't be captured using then or catch methods. And it's seems reasonable, because we don't need a pending response, because it will not have any data or error.

Creating Look-alike Promise Object:

Now, we know what is promise?, let's define our own Promise object DoYouLearnProgramming:

Defining DoYouLearnProgramming Object:

function DoYouLearnProgramming(programming) {
  let self = this;
  programming(function(msg) {
    self.resolve = msg;
  }, function(msg) {
    self.reject = msg;
  });
}
  • Here, I am declaring an object DoYouLearnProgramming which accept a callback function programming as an arugument.

  • The callback function - programming itself accepts two anonymous function as arguments.

  • I am setting the this.resolve and this.reject property to corresponding msg being passed to each anonymous functions.

  • And the callback function will be executed during instantiation.

Defining Prototype method:

DoYouLearnProgramming.prototype.then = function(arg) {
  if(this.resolve === undefined) {
    return this;
  } else {
    this.resolve = arg(this.resolve);
    return this;
  }
}

DoYouLearnProgramming.prototype.catch = function(arg) {
  if(this.reject === undefined) {
    return this;
  } else {
    this.reject = arg(this.reject);
    return this;
  }
}
  • Then, I am defining two prototype functions then and catch, which also accept an anonymous function as an argument.

  • Some conditionals checks were happening inside the function, which checks this.resolve and this.reject property value and perform the corresponding operations.

    • If the condition evaluates to true, it will return the object instance itself.
    • If the condition evaluates to false, it will set the corresponding property value, by executing the callback function with the corresponding property value passed as argument.

Instantiating DoYouLearnProgramming Object:

let p = new DoYouLearnProgramming(function(success, fail) {
  if(true) {
    success('You will be a developer');
  } else {
    fail('Develop something for you');
  }
});

Here, we are instantiating DoYouLearnProgramming by passing an anonymous function with two callback function as arguments like "we did with Promise object above", the corresponding callback will be executed based on the conditional.

The above code snippet will execute success callback function, which set the this.resolve property to "You will be a developer".

Capturing response

p.then(function(msg){
  console.log(msg);
}).catch(function(msg){
  console.log(msg);
})

Here, we are capturing the resolve value using then prototype method of DoYouLearnProgramming object, like we did above with Promise object.

This is my first article, please provide your feedbacks guys. Thank you

💖 💪 🙅 🚩
mathans1695
mathans1695

Posted on July 9, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related