If you go to watch a movie and there’s like 3 people ahead of you. They have the tickets ready and they let them in. When the time comes for you and say to the ticket checker “I don’t have my ticket with me and my wife is bringing. She is on her way and will be here any second. So can we just wait?”.
Then the time checker says “No I can’t do that buddy. There’s a line behind you and you need to step aside and when she comes back you can get in the line”.
If clone the V8 engine codebase and grep for things like setTimeout, DOM or HTTP request, they’re not in there and not exist in V8 which makes you a surprise. We call these things as WebAPI which are extra things that the browser provides.
For example, let take this function. This takes the number of seconds as an argument and executes for those number of seconds. If you call this function 3 as the input, the main JS thread will be blocked for the next 3 seconds and cannot do anything else.
If there is a button on the screen and right-clicking on it and it would not response for the next 5 seconds. That would be quite a bad user experience.
This code blocks the line of execution at the condition to check whether the network request has returned and in the meanwhile, the main thread or run time will remain block without making any other additional request or user inputs.
When the JS engine starts to execute the setTimeout function, the browser kicks off a timer for you. Other code will pop off the stack while setTimout() is in the web APIs. Web APIs can’t modify the code and web APIs pushes the callback to the task queue when it’s finished.
So what event loop does? If the stack is empty, It takes the first thing on the queue and pushes it on to the stack which effectively runs it.
Now check the gif below that I stole from Philip Roberts JS Conference 😛
02. Why do we need Callback Functions?
Let’s do the kind of mimic dummy memes on a server.
Without callbacks – In the following example, there is an array of 2 memes and they’re objects contain title and body attributes. In the getMemes() function, we’re mimicking how it is to fetch from a server and that could take a couple of seconds.
So here, I used setTimout which takes the callback function and it takes 2 seconds time delay whatever you put inside the callback function. The purpose of this function is to get all memes and put them on the page.
There is another function called createMeme() which takes a new Meme as a parameter. Use setTimeout here as well because we’re hypothetically dealing with the server. At there, I push a new Meme to the array.
Simply, we get all the mems and create another new meme.
Meme one and Meme two are there, but where is Meme three? It is because createMemes() took longer than getMemes(). getMemes() happen in 2 seconds and createMemes() took 3 seconds to execute. We can’t do anything beyond that point.
This is where asynchronous programming comes in and callbacks come in which is oneway to handle it. Now let’s make above it using callbacks.
With Callbacks –
The drawback of callback pattern – When handling sequential async behaviour, it often hard to read, debug or maintain. This referred to as callback hell.
Look at the following example where callbacks are used to verify the user.
Callbacks are everywhere. If you run the code and it works well but this is not sustainable. I can keep going with callbacks and code gets intended more when writing more code. This is not good.
Callback really makes sense for the idea of an event. For example, when the mouse is pressed and then trigger a function.
But if I want to sequence asynchronous things that happen in my program, it’s not a good idea. It means, I’m making all the API requests, asking for one thing first, another thing again and blah blah. Then callbacks can get very unwieldy. So we call it a callback hell.
A promise is an object that guarantees to deliver a single value. It can be either resolved value or a reason that it’s not resolved.
Once I have that promise as an object and I can do all sorts of things with it. Simply, Promise is an object that can be in a certain state. All Promises start off in the pending state and then at some unknown point in the future. They may transition to either fulfilled or rejected state. A Promise can have mainly 3 possible states,
(1) Pending – Waiting to get data back from the API
(2) Fulfilled – It means, successfully resolved. We have the results back from the API.
(3) Rejected – Some error has happened. Eg:- Network error for not resolved.
If you can take as Promise object, don’t need to query the promise continuously. Simply use then() and catch() methods.
(01) then() – Receives a function to be executed when it has been fulfilled. It’s a kinda callback function.
(02) catch() – Receives a function to be executed when it has been rejected.
1) Use promises if you have to use an asynchronous blocking code.
2) Use resolve() in .then method and reject() in .catch method for all practical purposes.
(01) XML HTTP requests
(02) Use a third-party library
What is Fetch? – Fetch is a function but promise-based HTTP request API. It allows you to fetch data, images, from all sorts of different kinds of places and do stuff with it.
Fetch returns a promise and the things that come from fetch should be converted into an object that we can use. That’s what I do with first then() method. In the second then(), will then have access to the response.
Note: response.json() also returns a promise.
What actually happens here in the following example?
(1) Fetch post from the API where id=1
(2) Take the response and convert into JSON
(3) Once I have the JSON, display the title of the post and fetch the first comment of the post using the API.
(4) Then take that response and convert it into JSON.
(5) Take the response and display the first name of the comment.
(6) Here, I no longer can be used as short handy as the above example because I have 2 lines of code in most then() methods.
Handling Errors – Error could happen and it could break either one of API URL is wrong. catch() method will catch any error and this is much nicer than having separate error callbacks for every single thing we do.
07. Promise.all, Promise. race, and promise.allSettled
If you have a lot of different promises, don’t have to keep having tons of .then() methods. Instead, you can use one following method according to your requirements.
(i) Promise. all() – This also returns the promise but fulfills only when all the promises are passed. If one promise is rejected, promise.all() returns rejected with reason.
In this example, a bunch of promises is created in a different way. These are all starting to run at the same time. If promise4 takes long time than others, they have to wait until promise4 is finished. It is going to take time for the longest promises takes.
(ii) Promise. race() – This is the same as promise.all() except for it’ll returns as soon as the first one is completed instead of waiting for everything to complete. It returns only one value.
(ii) Promise.allSettled() – Returns a Promise that resolves after every promise has returned success or failure.
Those of you who aren’t too familiar or comfortable with promises, after reading this part and you can able to create own promises. I guarantee everything will start to make a lot more sense. So we’re going to see 3 examples here.
(01) Using a promise to divide some numbers
(02) Wrapping set timeout function inside a promise.
(03) Connecting to a MySQL database using a promise.
(01) Using a promise to divide some numbers
Let’s see the first example of division right here and begin by defining a new function called `divide` which takes in 2 arguments which will be two numbers a and b. we’re going to return a divided by b. pretty straightforward.
If set the result in innerHTML and we should see 10 divided by 2 which equals 5. We get 5 right there. Okay so let’s start to convert this into a promise. This time we’re going to use .then() method and taking the function here which contains the result as the first parameter.
Let’s convert the divide() function to compatible with the above syntax there. Inside there, we’re going to start by returning a new instance of a promise. Promise constructor accepts a function and passes the function inside here. It will have 2 arguments resolve and reject.
Just keep in mind about resolver and reject. These are just 2 references to different functions. So the resolve() is going to be the function inside the then() when you’re using it and the reject() is going to be what’s inside the catch().
For the rejection, if we divide by zero then there’s an error. Let’s use the rejected function to handle the instance of dividing by zero. Use return statement to exit the promise function because we don’t want the code below there to continue running.
(02) Wrapping set timeout function inside a promise
Now let’s define a new function called waitTimer. We’re going be able to wait a certain number of milliseconds and then perform an action. So use the setTimeout function inside the promise.
Wait for 3,000 milliseconds then print to the DOM If something went wrong, then we’ll catch accepting the error.
Now let’s define a new function called waitTimer. We’re going be able to wait a certain number of milliseconds and then perform an action. So use the setTimeout function inside the promise and set wait for 3,000 milliseconds.
Print to the DOM If something went wrong and then we’ll catch accepting the error.
Now let’s learn the usage of async-await with easy examples.
(1) Async Functions – Start with async keyword and place before the function.
Async function always returns a promise. So you can use then() and catch() method to handle success or failure.
If you need, you can explicitly return a promise but the result would be the same.
10. Thumb rules of Async / Await
(1) Can’t use await in regular function – There would be a syntax error if we try to use await in regular function.
(2) Await doesn’t work in top-level code – await doesn’t work without an async function.
If you want to use it in top-level code, just wrap it with an anonymous function as below.
11. Error handling in Async / Await?
In case of rejection, we can catch the error using one of the following 2 methods.
1) Using of try..catch
2) Using of .catch() method. (Usually, this is not suited)
1) Using of try..catch –
If you want to catch errors in multiple lines, then do as below.
2) Using of .catch() method –
12. Should we use Promise or Async/ Await?
Before getting into the decision, let finalize what we understood in the promise chain and async-await. So I summarize it with the title of scope, logic and error handling.
Scope – Promise chain itself is asynchronous and the entire wrapper function is asynchronous in async-await.
Logic – Synchronous code can be handled in the same callback in the promise and need to move out of the callback in async-await.
Error Handling – While promise use then(), catch() and finally() method in a promise chain, async-await use try..catch and finally methods.
So the answer is both. let me explain why.
If you are trying to quickly grab the result from the promise and using them in one or 2 different ways, the promise chain would be the best option. Because it reduces the unnecessary async wrapper function when a simple then() method does.
If you find yourself writing long, then you have to write complicate waterfalls of then() statements but if you use async-await, it allows you to clean it up one readable asynchronous callback function.
If you have any questions or queries, let us know in the comment section below.
Binary Search Algorithm with Example | Data structuresG, 0 Comments Binary search will take less time than the linear search. The one pre-request of binary search- Array should be sorted. If the data is not sorted in the array, you cannot apply a binary...
React Interview Questions with Answers- (2020)G, 0 Comments Follow me on Medium In this article, we're going to talk all react interview questions with answers and will be useful for the people who get readying or for the interviews or want to improve the...