Promises Callbacks And Async/Await


First we have to understand two main concepts

  • Synchronous programming
  • Asynchronous programming

SYNCHRONOUS PROGRAMMING

It waits for each statement to complete its execution before going to next statement.

This approach can slow down application process if statements are not dependent on each other but still they are waiting for execution as they are in queue.

ASYNCHRONOUS PROGRAMMING

It does not wait for current statement to complete its execution before moving to next statement. e.g. calling a web service and executing file copy in JavaScript.

The call to web service can take some time to return a result meanwhile we can complete some other actions.

Once server provides the result, we can process that without waiting for it.

Our three approaches 1. Callbacks 2. Promises 3. Async/Await handles the asynchronous programming.

CALLBACKS

const articles = [
   {title:'First article'},
   {title:'Second article'}
];
function getArticles(){
   setTimeout(()=>{
      let articleContent='';
      articles.forEach((article,index)=>{
         articleContent+=`${article.title}`+` `;
         });
         console.log(articleContent);
      },1000);
   };
getArticles();

Here, we are simply created a article array and printed on console after 1 second.

The use of setTimeout function with 1 second time is just to showcase a behavior like from server.

Now what if we add a new article to the above list through another function

function createArticle(article){
   setTimeout(()=>{
      articles.push(article);
   },2000);
}

If we now call createArticle with new article and then getArticle we should get three articles but we get only first two articles

const articles = [
   {title:'First article'},
   {title:'Second article'}
];
function getArticles(){
   setTimeout(()=>{
      let articleContent='';
      articles.forEach((article,index)=>{
         articleContent+=`${article.title}`+` `;
         });
         console.log(articleContent);
      },1000);  
   };
   function createArticle(article){
      setTimeout(()=>{
         articles.push(article);
      },2000);
   }
createArticle({title:'Third article'});
getArticles();
//console output
"First article Second article "

Why is it so?

Because the execution of createArticle has 2 second timeout and in the meantime the getArticle completes its execution

Example

const articles = [
   {title:'First article'},
   {title:'Second article'}
];
function getArticles(){
   setTimeout(()=>{
      let articleContent='';
      articles.forEach((article,index)=>{
         articleContent+=`${article.title}`+` `;
      });
      console.log(articleContent);
   },1000);  
};
function createArticle(article, callback){
   setTimeout(()=>{
      articles.push(article);
      callback();
   },2000);
}
createArticle({title:'Third article'},getArticles);
//console output
"First article Second article Third article "

We have nested the call of getArticle inside the createArticle using callback.

Note the passing of getArticles as an argument to createArticle function. But this way, it gets complicated to nest the callbacks

PROMISES

With the use of promises, we dont require to pass callback function. Promises has two arguments resolve and reject. If function executes successfully we can call resolve() else we call reject()

const articles = [
   {title:'First article'},
   {title:'Second article'}
];
function getArticles(){
   setTimeout(()=>{
      let articleContent='';
      articles.forEach((article,index)=>{
         articleContent+=`${article.title}`+` `;
      });
      console.log(articleContent);
   },1000);
};
function createArticle(article){
   return new Promise((resolve,reject)=>{
      articles.push(article);
      let isError=false;
      if(!isError){
         resolve();
      } else {
         reject();
      }
   });
}
createArticle({title:'Third article'})
.then(getArticles());
//console output
"First article Second article Third article "
handling error with promises:
const articles = [
   {title:'First article'},
   {title:'Second article'}
];
function getArticles(){
   setTimeout(()=>{
      let articleContent='';
      articles.forEach((article,index)=>{
         articleContent+=`${article.title}`+` `;
      });
      console.log(articleContent);
   },1000);
};
function createArticle(article){
   return new Promise((resolve,reject)=>{
      articles.push(article);
      let isError=true;
      if(!isError){
         resolve();
      }else{
         reject('Something went wrong');
      }
   });
}
createArticle({title:'Third article'})
.then(getArticles())
.catch(error=>console.log(error));
//console output
"Something went wrong"

We called reject from createArticle and caught the error

Promise All

const promise1=Promise.resolve('Hello');
const promise2=100;
const promise3=new Promise((resolve,reject)=>{
   setTimeout(resolve,2000,'test');
});
Promise.all([promise1,promise2,promise3])
.then((values)=>console.log(values));
//console output
["Hello", 100, "test"]

We can combine the promises in one array and then use actual thenstatement instead of nesting then statements after each promise

we can use fetch api with jsonplaceholder

const promise0=fetch('https://jsonplaceholder.typicode.com/users').then(res=>res.json());
const promise1=Promise.resolve('Hello');
const promise2=100;
const promise3=new Promise((resolve,reject)=>{
   setTimeout(resolve,2000,'test');
});
Promise.all([promise0,promise1,promise2,promise3])
.then((values)=>console.log(values));

ASYNC / AWAIT

To use await on statement the function should be marked as async

<!DOCTYPE html>
<html>
<head>
<title>Async/Await Example</title>
</head>
<body>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
   const articles = [
      {title:'First article'},
      {title:'Second article'}
   ];
   function getArticles(){
      setTimeout(()=>{
         let articleContent='';
         articles.forEach((article,index)=>{
            articleContent+=`${article.title}`+` `;
         });
         console.log(articleContent);
      },1000);
   }
   function createArticle(article){
      articles.push(article);
   }
   async function testAsync(){
      await createArticle({title:'Third article'});
      getArticles();
   }
   testAsync();
   //console output
   // First article Second article Third article
</script>
</body>
</html>

testAsync function is marked as async and we used await for createArticle function to complete it first. Then we called getArticles().

Use of async / await are the better version of promises and makes it more clean code

Updated on: 04-Sep-2019

683 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements