{"id":60706,"date":"2024-03-20T12:15:39","date_gmt":"2024-03-20T06:45:39","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=60706"},"modified":"2024-03-21T12:18:42","modified_gmt":"2024-03-21T06:48:42","slug":"unraveling-javascript-promises-a-solution-to-callback-hell","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/unraveling-javascript-promises-a-solution-to-callback-hell\/","title":{"rendered":"Unraveling JavaScript Promises: A Solution to Callback Hell"},"content":{"rendered":"<p>Before the widespread adoption of promises, callback hell was a common issue in JavaScript.\u00a0 Callback hell refers to the situation where multiple nested callbacks are used to handle asynchronous operations, leading to code that is difficult to read, understand, and maintain.In callback hell, asynchronous functions would often be nested within each other, resulting in a pyramid-like structure of code. This made the code hard to follow, prone to errors, and challenging to debug or refactor.<\/p>\n<p>Promises were introduced in ECMAScript 6 (ES6) as a solution to this problem. Promises provide a cleaner and more readable way to handle asynchronous operations by representing a value that may be available in the future. Promises allow developers to chain asynchronous operations together using methods like <code>.then()<\/code> and <code>.catch()<\/code>, which makes the code more linear and easier to understand.<\/p>\n<p style=\"text-align: left;\">Below is the example of callback hell, later we will see, how to solve this using Promises:<\/p>\n<pre><code>\/\/ Function to simulate asynchronous task 1\r\nfunctiontask1(callbackFn) {\r\n    setTimeout(() =&gt; {\r\n        console.log(\"1\")\r\n        callbackFn()\r\n    }, 1000);\r\n}\r\n\/\/ Function to simulate asynchronous task 2\r\nfunctiontask2(callback) {\r\n    setTimeout(function() {\r\n        console.log(\"Task 2 completed\");\r\n        callback();\r\n    }, 1500);\r\n}<\/code><\/pre>\n<pre><code>\/\/ Function to simulate asynchronous task 3\r\nfunctiontask3(callback) {\r\n    setTimeout(function() {\r\n        console.log(\"Task 3 completed\");\r\n        callback();\r\n    }, 500);\r\n}<\/code><\/pre>\n<pre><code>\/\/ Nested callbacks to execute tasks sequentially\r\ntask1(function() {\r\n    task2(function() {\r\n        task3(function() {\r\n            console.log(\"All tasks completed\");\r\n        });\r\n    });\r\n});<\/code><\/pre>\n<p>\/\/ Output<br \/>\n\/\/ Task 1 completed<br \/>\n\/\/ Task 2 completed<br \/>\n\/\/ Task 3 completed<br \/>\n\/\/ All tasks completed<\/p>\n<h2>Creating a Promise<\/h2>\n<div>\n<pre><code>const myPromise = new Promise((resolve, reject) =&gt; {\r\n    \/\/ Simulating an asynchronous operation (e.g., fetching data from a server)\r\n    setTimeout(() =&gt; {\r\n        \/\/ Assuming the operation was successful\r\n        const data = {\r\n            message: \"Data successfully fetched\"\r\n        };\r\n\r\n        \/\/ Resolve the promise with the data\r\n        resolve(data);\r\n\r\n        \/\/ If the operation fails, reject the promise\r\n        \/\/ reject(new Error(\"Failed to fetch data\"));\r\n    }, 2000); \/\/ Simulating a delay of 2 seconds\r\n});<\/code><\/pre>\n<p>In this example:<\/p>\n<ul>\n<li>We create a new promise using the <code>Promise<\/code> constructor, which takes a function with two parameters: <code>resolve<\/code> and <code>reject<\/code>.<\/li>\n<li>Inside the function, we simulate an asynchronous operation using <code>setTimeout<\/code>. This could be any asynchronous task, such as fetching data from a server.<\/li>\n<li>If the operation is successful, we call <code>resolve<\/code> with the data we want to pass<\/li>\n<li>If the operation fails, we call <code>reject<\/code> with an error object<\/li>\n<\/ul>\n<p>Let&#8217;s try consoling myPromise variable, and see what it will show<\/p>\n<\/div>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-60705 size-large\" src=\"https:\/\/www.tothenew.com\/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-2024-03-08-at-9.44.56-PM-1024x668.png\" alt=\"\" width=\"625\" height=\"408\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-2024-03-08-at-9.44.56-PM-1024x668.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-2024-03-08-at-9.44.56-PM-300x196.png 300w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-2024-03-08-at-9.44.56-PM-768x501.png 768w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-2024-03-08-at-9.44.56-PM-1536x1003.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-2024-03-08-at-9.44.56-PM-624x407.png 624w, \/blog\/wp-ttn-blog\/uploads\/2024\/03\/Screenshot-2024-03-08-at-9.44.56-PM.png 2022w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<div>\n<p>There are 2 things, one is Promise state and another is result.<\/p>\n<p>Promise <strong>state<\/strong> &#8211; It tells in which state promise is in, like initially it is in pending state and then either it can be fulfilled or rejected. If fulfilled, it means operation completed successfully, if rejected, then it means the the operation gets failed.<\/p>\n<p>Promise <strong>result<\/strong> : It holds the data of the promise<\/p>\n<\/div>\n<h3>How to consume a Promise<\/h3>\n<p>we can consume a promise using the <code>.then()<\/code> and <code>.catch()<\/code> methods.<\/p>\n<div>\n<pre><code>myPromise.then((data) =&gt; {\r\n    console.log(\"data\", data)\r\n}).catch((err) =&gt; {\r\n    console.log(\"err\", err)\r\n})<\/code><\/pre>\n<p>Here&#8217;s what each part does:<\/p>\n<ol>\n<li><code>myPromise.then((data) =&gt; { ... })<\/code>: This part of the code registers a callback function to be executed when the promise is resolved successfully.<\/li>\n<li><code>.catch((err) =&gt; { ... })<\/code>: This part of the code registers a callback function to be executed if the promise is rejected (i.e., an error occurs during its execution).<\/li>\n<\/ol>\n<p>So, when <code>myPromise<\/code> resolves successfully, the first callback function inside <code>.then()<\/code> is executed, logging the data to the console. If <code>myPromise<\/code> is rejected (i.e., an error occurs), the callback function inside <code>.catch()<\/code> is executed, logging the error to the console.<\/p>\n<p>Now, let&#8217;s go back to the first example which is of callback hell, and let&#8217;s solve it using promises:<\/p>\n<pre><code>\/\/ Function to simulate asynchronous task 1\r\nfunctiontask1(callbackFn) {\r\n    setTimeout(() =&gt; {\r\n        console.log(\"1\")\r\n        callbackFn()\r\n    }, 1000);\r\n}\r\n\/\/ Function to simulate asynchronous task 2\r\nfunctiontask2(callback) {\r\n    setTimeout(function() {\r\n        console.log(\"Task 2 completed\");\r\n        callback();\r\n    }, 1500);\r\n}<\/code><\/pre>\n<pre><code>\/\/ Function to simulate asynchronous task 3\r\nfunctiontask3(callback) {\r\n    setTimeout(function() {\r\n        console.log(\"Task 3 completed\");\r\n        callback();\r\n    }, 500);\r\n}<\/code><\/pre>\n<pre><code>\/\/ Execute tasks sequentially using promises\r\ntask1()\r\n    .then(() =&gt; task2())\r\n    .then(() =&gt; task3())\r\n    .then(() =&gt; {\r\n        console.log(\"All tasks completed\");\r\n    })\r\n    .catch((error) =&gt; {\r\n        console.error(\"An error occurred:\", error);\r\n    });<\/code><\/pre>\n<p>So, that&#8217;s how easily we can do it through promises. Now, to simplify it further, we can also use async\/await. Async\/await is just syntactic sugar for the <code>then<\/code> block.<\/p>\n<\/div>\n<pre><code>async function executeTasks() {\r\n    try {\r\n        await task1();\r\n        await task2();\r\n        await task3();\r\n        console.log(\"All tasks completed\");\r\n    } catch (error) {\r\n        console.error(\"An error occurred:\", error);\r\n    }\r\n}\r\n\r\nexecuteTasks();\r\n<\/code><\/pre>\n<p><strong>Defining Promise<\/strong>: A Promise is an object that represents eventual completion(or failure)\u00a0 of async operation.<\/p>\n<h2><strong>Conclusion<\/strong><\/h2>\n<p>Both solutions, using the <code>then<\/code> block and <code>async\/await<\/code>, produce the same result as the one provided by the callback function. However, writing with async functions is much easier now. Stay tuned for more such blogs.<\/p>\n<div class=\"ap-custom-wrapper\"><\/div><!--ap-custom-wrapper-->","protected":false},"excerpt":{"rendered":"<p>Before the widespread adoption of promises, callback hell was a common issue in JavaScript.\u00a0 Callback hell refers to the situation where multiple nested callbacks are used to handle asynchronous operations, leading to code that is difficult to read, understand, and maintain.In callback hell, asynchronous functions would often be nested within each other, resulting in a [&hellip;]<\/p>\n","protected":false},"author":1714,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":49},"categories":[3429,4684,1185,3038,1],"tags":[5699],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/60706"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1714"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=60706"}],"version-history":[{"count":6,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/60706\/revisions"}],"predecessor-version":[{"id":60899,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/60706\/revisions\/60899"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=60706"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=60706"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=60706"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}