Callbacks, Promises, async, await, try, catch - Heart of Javascript
Callbacks, Promises, async, await, try, catch - Heart❤️ of JavaScript
The whole purpose boils down to having Synchronous or Non-Blocking code and let's understand it now, 👇
Most Important thing - Why? - Why we at all need Callbacks, Promises, Async, Await ?
Because JavaScript is always in hurry to go through line by line fastly (asynchronous execution). And it differentiate with the code, will talk about this later also. It instantly executes and completes one part of code and doesn't another by skipping on it.
Firstly, let's see which kind of code gets executed instantly with no need of extra time ⏩. (doesn't asks for "time-please").
Work Identifiers
Initialization and Updation of Variables let myUser= "Binod", let users = [], users.push(myUser);
Loops for(let user of users){}, users.map((user)=>{});
Secondly, let's see which kind of code need extra time to complete and gets skipped. (asks for "time-please"🐌⌛).
Work Identifiers
Calling an API fetch, axios etc..
Delay delay(2000);
Reading file fs.readFile("myFile","utf-8", callbackFunction)
Using setTimout setTimout(Workfunction , 2000);
Calling an await function await anyFunction();
CURD in Database await db.user.find({});
etc... such kind of code needs time to finish.
Now, We'll have to understand the different execution style of both different type of code above.
Firstly, the first kind of code that doesn't asks for "time-please", The JavaScript decides let's completely execute this right away and move on.
But,
On the other hand, the second kind of code which do ask for "time-please", naturally the JavaScript doesn't likes to wait, so it decides to come back to this code later after it finishes, and so for now let's move on. This behavior is called Asynchronous execution of code.
Problem Statement (Problem with the above Asynchronous behavior) :
The problem arises in a case where the next underlying code depends of the complete execution of it's above written code.
For Example:-
CODE
let myObj;
// this readFile function asks for "time-please"
myObj = fs.readFile("file.txt","utf-6", (err, fileData)=>{
console.log("this is the file data: ", fileData);
});
console.log("following next line, I want to execute this line after reading contents of file.txt");
console.log("End");
OUTPUT
following next line, I want to execute this line after reading contents of file.txt
End
this is the file data: ....
So, the problem here is that the lines are not executed complete in sequence, the asynchronous JS didn't waited to read the file and finish up, but it skipped and jumped to the next following line. Till now we understood the problem statement completely.
Now it's time for the solutions to the above stated problem statement:
1. Callbacks nesting
Callbacks are very basic, easy but weird solution to our problem statement, let's directly see the solution through callbacks:
CODE
let myObj;
// this readFile function asks for "time-please"
myObj = fs.readFile("file.txt","utf-6", (err, fileData)=>{
console.log("this is the file data: ", fileData);
console.log("following next line, I want to execute this line after reading contents of file.txt");
});
console.log("End");
OUTPUT
End
this is the file data: ....
following next line, I want to execute this line after reading contents of file.txt
Notice that we somewhat made the reading of the file and printing the next following file wanted synchronous to each other by writing them inside callback sequencially.
The problem with this is callback hell (many callback nesting together):
Till yet we didn't introduced the concept of promise.
Now, it's time for some promises :p
2. Promises
To save us from the above shown callback hell and to overall make our life simpler by introducing synchronicity in our code we use this very easy concept called Promises.
What is a promise?
Basically a promise is an object (seems easy right? it actually is !).
A JavaScript Promise object can be:
- Pending
- Fulfilled
- Rejected
The Promise object supports two properties: state and result.
While a Promise object is "pending" (working), the result is undefined.
When a Promise object is "fulfilled", the result is a value.
When a Promise object is "rejected", the result is an error object.
myPromise.state | myPromise.result | |
---|---|---|
"pending" | -> undefined | |
"fulfilled" | -> a result value | |
"rejected" | -> an error object |
NOTE:- We can store the promise from any promise returning function directly into any object.
In our Analogy, promise is a proper format slip of "time-please" request. :p
We use promiseObject.then to get the data in both fulfilled state and rejected state. We use promiseObject.catch to get the error(kind of a data only) in rejected state of the any promise stored in promiseObject.
NOTE: We can use second argument of .then function to get the error.🤯 (I've discussed about this in a different blog in detail).
Let's see the syntax:
CODE
let promiseObject = fs.readFile("file.txt", "utf-8"); // this readFile function asks for "time-please"
console.log(promiseObject); // this will give us undefined
promiseObject.then((data)=>{ // this is the syntax of reading a fulfilled promise
console.log("this is the file data: ", data);
console.log("following next line, I want to execute this line after reading contents of file.txt");
});
console.log("End");
OUTPUT
undefined
End
this is the file data: ...
following next line, I want to execute this line after reading contents of file.txt
3. Await
General Human behavior - If someone promised us something and she's taking some time to get back to you. So generally what you'll do ? Yes, you'll wait endlessly for her to get back to you and hope for the best only. :p
Similarly,
To do so in JS, we use await. Simple !
Finally this gives us the power to make JS completely synchronous.
NOTE:- await can only be used inside an async function (We'll learn about async in point no. 5).
NOTE:- await only receives the data on a fulfilled state of a promise. (as also seen in our Analogy- hoping for the best only). 🤯
p.s.: We'll see how to handle the rejected state of a promise just after the following code.
CODE
let promiseObject = await fs.readFile("file.txt", "utf-8"); // this readFile function asks for "time-please" but now using await we are waiting for it right here to finish up before moving on further.
console.log("this is the file data: ",promiseObject);
console.log("following next line, I want to execute this line after reading contents of file.txt");
console.log("End");
OUTPUT (one of the best yet)
this is the file data: ....
following next line, I want to execute this line after reading contents of file.txt
End
Now, you must be guessing how to handle the case if the promise is rejected !
4. try and catch
Let's see, while using await we handle the rejected state of a promise using try, catch statements.
CODE (notice how I just copied the same above code inside a try block)
try{
let promiseObject = await fs.readFile("file.txt", "utf-8"); //
this readFile function asks for "time-please" but now using await we
are waiting for it right here to finish up before moving on further.
console.log("this is the file data: ",promiseObject);
console.log("following next line, I want to execute this line after reading contents of file.txt");
console.log("End");
}
catch(err){ //
this is where the error comes from the rejected promise.
console.log(err);
}
Pro Tip : catch(error) {...}
statement catches only awaited rejected promises in try {...}
statement.
5. Async
Simply put, async makes a function return a Promise (Remember our Analogy of a Promise ? - a proper format slip of "time-please" request).
So, I we make any function async it will return a promise.
CODE
const myFunction = async() => {
return "Hello";
}
console.log(myFunction()); // this prints a promise object
Bonus - let's see an alternative method to make a function return a promise.
6. Bonus
Another way of making a promise returning function other than async :
const myFunction = async() =>{
return new Promise((resolve, reject)=>{
resolve("Hello"); // fulfills the promise
})
}
That's all, I hope This Blog strengthened and set your concepts in JS once in for all. ✌️
Happy Coding :)
"Write to Learn"
Comments
Post a Comment