Callbacks in JavaScript
Tags: callbacks, javascript
Published: 2019-06-04 03:45:26

---
title: Callbacks in JavaScript
published: true
description: Callbacks in JavaScript
tags: callbacks, JavaScript
---

<div id="toc_container">

<div class="toc_title">

Table of Contents </div>
<ul class="toc_list">
<li><a href="https://fullstackgeek.blogspot.com/2019/02/asynchronous-javascript-explained-for-beginners.html#Callbacks"> Callbacks in JavaScript</a></li>

<li><a href="https://fullstackgeek.blogspot.com/2019/02/asynchronous-javascript-explained-for-beginners.html#HittingHTTPRequests"> Hitting HTTP Requests in JavaScript</a></li>

<li><a href="https://fullstackgeek.blogspot.com/2019/02/asynchronous-javascript-explained-for-beginners.html#CallbackAbstraction"> Callback Abstraction</a></li>

</ul>

</div>



<div class="custom_heading_h2_div">
<h2 class="custom_heading_h2" id="Callbacks">
Callbacks in JavaScript:</h2>
<div>
<a href="https://fullstackgeek.blogspot.com/2019/02/asynchronous-javascript-explained-for-beginners.html#Callbacks">Callbacks</a> are simply <a href="https://fullstackgeek.blogspot.com/2019/01/functions-in-javascript.html" target="_blank">Functions In JavaScript</a> which are to be called and then executed after the execution of another function has finished. So how it happens? Actually, In JavaScript, functions are itself considered as objects and hence as all other objects, even functions can be sent as arguments to other functions. The most common and generic use case one can think of is setTimeout() function in JavaScript.<br />

Consider the following Example of setTimeout() in JavaScript and hence try to get hands-on Callbacks JavaScript gave to us by default.
          
<div id="code_block_custom">
<pre>//with customary function signature  
setTimeout(function() {  
  console.log('hello1');  
}, 1000);  

//with arrow function signature  
setTimeout(() =&gt; {  
  console.log('hello2');  
}, 2000);  
        </pre>
</div>
<br />
In the above example, I have used setTimeout() function by passing a callback function as an argument into it along with the second argument which is simply the no of milliseconds after which our callback function would get executed. I have shown two ways of passing a callback function here, one is the more of customary approach and the second one is with arrow function approach which is a bit modern way.</div>
</div>
<div class="custom_heading_h2_div">
<h2 class="custom_heading_h2" id="HittingHTTPRequests">
Hitting HTTP Requests in Javascript:</h2>
<div>
Suppose, I want to hit an HTTP Request to an API which fetches a random text for me. We won't be digging much into details of hitting HTTP Requests as this is out of the scope of this article.
        </div>
<br />
Now, to hit that API, you need to create two files:<br />
<br />
<div>
<u>index.html</u>
            <br />
<div id="code_block_custom">
<pre> &lt;!DOCTYPE html&gt;  
 &lt;html&gt;  
   &lt;head&gt;&lt;/head&gt;  
   &lt;body&gt;  
     &lt;script src="app.js"&gt;&lt;/script&gt;  
   &lt;/body&gt;  
 &lt;/html&gt;  
        </pre>
</div>
<br />
<u>app.js</u>
            <br />
<div id="code_block_custom">
<pre> const puzzleAPIhit = () =&gt; {  
   const request = new XMLHttpRequest()  
   request.addEventListener('readystatechange', (e) =&gt; {  
     if (e.target.readyState === 4 &amp;&amp; e.target.status === 200) {  
       const data = JSON.parse(e.target.responseText);  
       console.log(data.puzzle)  
     } else if (e.target.readyState === 4) {  
       console.log('An error has taken place')  
     }  
   })  
   request.open('GET', 'http://puzzle.mead.io/puzzle?wordCount=3')  
   request.send()  
 }  
 puzzleAPIhit(); 
        </pre>
</div>
<br />
Now, when you open the "index.html" file in your browser, you can see a random string getting printed in the console.
<br /></div>
</div>
<div class="suggested_read_block">
Suggested Read:&nbsp;<a href="https://fullstackgeek.blogspot.com/2019/04/redis-vs-mysql-benchmark.html" target="_blank">Redis vs MySQL Benchmarks</a></div>
<br />
<br />
<div class="custom_heading_h2_div">
<h2 class="custom_heading_h2" id="CallbackAbstraction">
Callback Abstraction:</h2>
<div>
Now, what if we have a complex application or something like an entire game is built over this and hence the logic of generation of a random string is something which we should keep hidden or abstract from "users". To understand this, we can create three files:
        </div>
<br />
<u>index.html</u>
        <br />
<div id="code_block_custom">
<pre> &lt;!DOCTYPE html&gt;  
 &lt;html&gt;  
   &lt;body&gt;  
     &lt;script src="makerequest.js"&gt;&lt;/script&gt;  
     &lt;script src="app.js"&gt;&lt;/script&gt;  
   &lt;/body&gt;  
 &lt;/html&gt; 
      </pre>
</div>
<br />
<u>makerequest.js</u>
        <br />
<div id="code_block_custom">
<pre> const puzzleAPIhit = () =&gt; {  
   return 'some random string';  
 }  
      </pre>
</div>
<br />
<u>app.js</u>
        <br />
<div id="code_block_custom">
<pre> const myPuzzle = puzzleAPIhit();  
 console.log(myPuzzle);  
      </pre>
</div>

Now, we need to replace the actual logic of finding the random string with the hardcoded return statement in puzzleAPIhit() function. But as the hitting of an HTTP request is asynchronous nature, we can't simply do this: (changing contents of makerequest.js and keeping rest two files intact)<br />
<br />
<u>makerequest.js</u>
        <br />
<div id="code_block_custom">
<pre> const puzzleAPIhit = () =&gt; {  
   const request = new XMLHttpRequest()  
   request.addEventListener('readystatechange', (e) =&gt; {  
     if (e.target.readyState === 4 &amp;&amp; e.target.status === 200) {  
       const data = JSON.parse(e.target.responseText);  
       console.log(data.puzzle)  
       return data.puzzle;   
       /*  
         This is absolutely impossible the request.open() is   
         asynchronous in nature.  
       */  
     } else if (e.target.readyState === 4) {  
       console.log('An error has taken place')  
     }  
   })  
   request.open('GET', 'http://puzzle.mead.io/puzzle?wordCount=3')  
   request.send()  
 }    </pre>
</div>
<br />
Because in the console, it would be printing:
        <br />
<div id="code_block_custom">
<pre> undefined  
 Reliable Public Transportation //A random string  
    </pre>
</div>
<br />
It is happening because, as the request.open() is asynchronous in nature, inside app.js, this is what happens:<br />
<ul style="text-align: left;">
<li>"puzzleAPIhit()" starts its execution but being asynchronous, it would move to the next statement while parallelly running the HTTP request.</li>
<li>"console.log(myPuzzle);" gets executed even before the execution of "puzzleAPIhit()" is completed and hence prints undefined.</li>
</ul>
<br />
Solution? use <b>callbacks. </b>Here's what we can do:
        <br />
<br />
<u>app.js</u>
        <br />
<div id="code_block_custom">
<pre> const myPuzzle = puzzleAPIhit((error, puzzle) =&gt; {  
   if(error) {  
     console.log(`Error: ${error}`)  
   } else {  
     console.log(puzzle)  
   }  
 });  
    </pre>
</div>
<br />
<u>makerequest.js</u>
        <br />
<div id="code_block_custom">
<pre> const puzzleAPIhit = (callback) =&gt; {  
   const request = new XMLHttpRequest()  
   request.addEventListener('readystatechange', (e) =&gt; {  
     if (e.target.readyState === 4 &amp;&amp; e.target.status === 200) {  
       const data = JSON.parse(e.target.responseText)  
       callback(undefined, data.puzzle)  
     } else if (e.target.readyState === 4) {  
       callback('An error has taken place', undefined)  
     }  
   })  
   request.open('GET', 'http://puzzle.mead.io/puzzle?wordCount=3')  
   request.send()  
 }  
    </pre>
</div>
<br />
<u>index.html (no change)</u><br />
<br />
<div>
What we have done? We have just replaced the synchronous call to asynchronous one by sending the callback in puzzleAPIhit() as an argument. And in the method puzzleAPIhit() itself, we called the callback after we have got our results which validates the basic definition of callbacks.
            <br />
<br /></div>
</div>
</div>