Learn about the JavaScript event loop, which is a core concept that is helpful for every developer to master. Through animations and diagrams, you will learn how JavaScript manages asynchronous tasks while remaining singlethreaded. You will learn the critical differences between the call stack, web APIs, the callback Q, and the high priority microtask Q. By the end of this video, you will have a visual understanding of how these components work together to keep your applications running smoothly without blocking. Viswas created this course. Event loop is one of the most important concept in JavaScript and honestly one of the most misunderstood one. A lot of developer uses a synchronous code every day like it could be a promises, it could be observables when we go with the angular, it could be timers or it could be making the API calls and fetching the data from the server. But when it comes how things actually works under the hood, then things getting confusing. But here is reality. If you understood a synchronous JavaScript and event loop in depth then you are able to crack almost every front- end interview and most importantly you will think like a senior or strong developer who understand how exactly JavaScript works internally. Now when we go under the hood, the event loop is just a small part of the bigger system. In the browser or JavaScript runtime, we have a JavaScript engine with call stack. We have a web API environment for connecting with outside word. Then we have a task Q, microtask Q. And finally we have a event loop which will connect everything together and all of these component works together to make the JavaScript non-blocking even through it is singlethreaded. So before jumping into the complex scenarios let's start from absolute basic. You know that JavaScript is single threaded means we have only one call stack and this call stack manages the execution order of your program. Now to understand the call stack let me go with very simple JavaScript example. We have console.log with start. Then we have a function definition. We are calling the function. And finally we have console.log log for end. And we know that before even executing this single line of code, JavaScript creates the memory for all the variables and functions and it will create the global execution context. That global execution context is added into the call stack. And now we have execution of first line. When we execute the first line, we have console.log log printed on your console then JavaScript will move to the next line. We don't have anything to execute here and it will directly go to the function call. When we have a function call, JavaScript creates the new execution function context and that is again pushed into the call stack. And now we have function execution here. So we have console.log log that is with run and that is printed on the screen and we completed our function execution. As soon as this function execution is completed, the function execution context will be popped out of the call stack. JavaScript will move to the next line and we are done with our script. Here end will be printed in the console. And once we are done the script execution, the global execution context is also deleted from the call stack. And this is how call stack manages the execution order of your program and make sure that only one thing works at a time in the sequence. Every function call is pushed into the call stack, executed and popped out of the call stack when its execution is completed. Simple, predictable and perfect for your synchronous code. But here where things getting interesting, this approach work flawlessly when your code run line by line without waiting for anything. But real life applications are not that much simple right. What happen when we need to wait for something? We might need to use the timers in your code. You might needs to make the API call or we need to connect with different resources. Right? And call stack cannot handle that alone. We have only one call stack and its duty just to execute anything comes inside it. It does not have ability to pause the task or delay the execution of task. Right? And if it had that ability, it could be work on only one longunning task and that task is continuously executing in call stack, right? and it will basically block the execution of all other task. It could slow down your application or even completely freeze your application. Right? And that is not ideal. In web application, we often needs to connect with the external resources like we might needs to visit any of the server and fetch data from there. We needs to work on updating the DOM by accessing the different elements. Then we need to store the data in local storage or access it. We might need to work with timer. It could be a set timeout or set intervals. And we need to work on promises, right? We can make the API call fetch the data and uh in that between need to wait for getting the response or you might need to work on event. We can have a button and add the event on that and on click of that button something will execute and to handle all those task JavaScript relies on additional superpower that is present outside call stack and we will get all those superpower through web APIs. Now let's understand what are the web APIs. Web APIs is functionality provided by the browser environment or JavaScript runtime but not by JavaScript itself. Web APIs provide set of interfaces that allow you to connect with external resources which includes timer, network request, DOM manipulation, user events, storing the data in the browser and much more. And we have a number of APIs available. We will discuss few of the most important one. And the first one is timer. It is used for scheduling the execution. We can have the set timeout, set interval. We can access those APIs through timer web API environment and that is mainly used for delaying some execution. Then we have a next web API that is related to HTTP or network request and uh that is fetch. We are using fetch for calling the backend services to accessing the DOM elements. We are using different DOM APIs. It could be document dot getelement by id, create element, append child and all those functions we can access through DOM APIs for updating our UI dynamically. Next we have event APIs. We need to add some event listener on any of the element and we are accessing those functions through event APIs. Apart from that we have some important APIs related to storage. we need to access the local storage, session storage. And for storing the data in the browser, we need to use the storage APIs. We might need to access user current location. For this purpose, we have JOC APIs. Then we are using console.log, right? And that is part of console API. We might need to hit some URL and fetch some data from the server, right? And for that we are using URL API. We have few more related to media or canvas, websockets, web workers and all those API help us to connect with the external word and get require functionality in the browser or JavaScript code and whatever you are seeing here whether it is timer multiple events APIs, console, URL those are part of web API. environment that is not part of core JavaScript. Most of the people think that this web APIs is part of the JavaScript but that is not true. Since this web APIs are provided by the browser, we can directly use them into browser or JavaScript code through global or window object. Now we understood how exactly the synchronous code work in JavaScript line by line and we also understood what are the different web APIs but we still have very important questions how exactly JavaScript handle the delay or a synchronous code executions right and this is where some of the web APIs play a key role they help in handling these operations outside the call stack so that JavaScript can remains non-blocking and continue executing other code. Now let's start with very simple example and we will understand how exactly delay handle in JavaScript by using the timer web APIs and using the set timeout function. We are starting with console. Then we have a set timeout. It will take the call back function with a delay of 4 seconds and then we have console.lo lock at the end of the script and we know that what will be the output right first we will have the start here then this call back function will needs to wait for 4 second so JavaScript mode to the next line it will print the end and after 4 second delay it will print the call back so output will be start end and call back but we will understand how exactly things works under the hood we know that Before starting even single line of code, JavaScript creates global execution context and that execution context is added into the call stack. And in this code, we are using couple of web APIs, right? The first one is console and the second one is timer API for set timeout. So we will list down those two APIs here. And now JavaScript started execution with line number one. We have console here. So, JavaScript delegate this to console web APIs. It will execute that particular console.log statement and it will print start on console. Now we move to the next line and on next line we have a set timeout. We will required one more web APIs and this set timeout will be delegated to timer web APIs. Now it's responsibility of the timer web APIs to handle next thing. It will register the timer store that call back function along with registered timer. Here we are seeing the call back function and that function will be passed as a first parameter to your set timeout. Here I'm using the arrow function and we don't see any call back name but you can consider name of this function as a call back. Hope you are clear till this point. Now this call back function is registered in the web API environment and this timer is also started countdown. But we know that call stack cannot wait for anything. If it's waiting for this timer to execute then we are not able to handle other task. So JavaScript and call stack will move to the next line. Again we have console.log statement. So internally this console web APIs will be called and it will print end on console. We are done with our script execution and as soon as script execution is completed this global execution context will be popped out of the call stack. Meanwhile this timer is still running in the background. It is counting down from 4 3 2 1 till zero. As soon as these 4 seconds are completed, this call back function is ready to execute. But now here is important part. We know that everything in JavaScript is executed inside call stack. So somehow this call back function needs to come back into the call stack to start its execution. And once it reaches to call stack, the job of the call stack is simple. just to quickly execute that function and print this on console. And now we have one very big question. How exactly this call back function will get back into the call stack and where exactly the call back Q and event loop comes in picture. Once the timer is completed and this call back function is ready for execution, it cannot directly go into call stack because in call stack we might be doing some another task and if this call back function directly added it could disturb the existing task that is already running in. So it needs to follow the different approach. And here now we have task Q and the event loop comes in picture and play a very important role. Once this function is ready for execution now it will go to the call back Q. We will see this is added into the call back queue and the job of the event loop starts from here. The event loop continuously check for two things. The first one is the call stack and the second one is this task or call back Q. And once it see the call stack is empty, it will check if we have anything in call back Q for execution. And if we have anything, it will quickly pick it and add that into the call stack. In our case, this call back function sits in task or call back Q. The event loop detects it and move this call back function into call stack. And now this call back function start executing. Internally the execution context will be created for this call back function. And actually that call back function execution context run in call stack. Call stack quickly executed. The call stack is empty now and this call back is printed on the console. Hope you are clear with this first example. The event loop play very important role and its main job is to check for this call back or the task Q and if we have anything for execution add that into the call stack. The responsibility of the event loop is very simple but really important. We will understand that with the help of simple visual. Here we have three different task waiting in call back Q. The event loop continuously check if call stack is empty or not. In our case the call stack is empty and nothing is currently executing. It will pick first task from call back Q. See here the first task will be picked by the event loop and added into the call stack. Now that task is executing. Once that task is completed, the call stack is empty again. But what if something is already running in call stack like we have global execution context and we could have couple of function execution context that is already present in the call stack and we have something waiting in call back Q as well. In this case the event loop wait patiently. It will not interrupt or push any task into call stack. It will wait until all the task from the call stacks are completed. And once call stack is empty again it is active now and it will pick the next task from the call back queue and add into the call stack. That task is executing now. Once that task is executed, call stack is empty again. And event loop again check if the call stack is empty. In our case, it is empty. Now it will pick task three and add that into the call stack. And once that task execution is done, the call stack is empty now. And our call back Q is also empty. That means all our execution is completed. And this is how the event loop play very important role and acts as a bridge between your cues and call stack. Key rule event loop never add any task into the call stack until call stack is completely empty. And this is how entire flow works together making JavaScript behave a synchronously even through it is singlethreaded synchronous programming language. Now to strengthen our concept more let's go with another example and in this example we will understand one more web APIs and that is Jolocation services. We have very simple code here. We are using go location service and through which we are trying to get the current location of user. If user approve it, we will get current position. If user deny it, we will get error. So let's start with first step. Before executing any line of code, JavaScript create global execution context and that is added into call stack. And for this code we are using two web APIs. First one is Jolocation and second one is console. So both APIs are listed here. Then we will start the execution of first line. And this get current position method added into the call stack. JavaScript C this method is belongs to web API. So JavaScript does not execute it by itself. It hand over this request to Jolocation API. Then this get current position method is executed by go location APIs and then browser start the asynchronous work. It will show this kind of model in the browser and it will ask for users permission. It will ask you for the GPS or the location. Meanwhile, call stack will continue do its execution. Right? It see like this particular function is passed to web API. So it will move to the next line and here your code execution is completed. So global execution context will be popped out of the call stack and the call stack is empty. Now then we don't know how much time user will take to give this permission right. It can give it immediately or even he can reject it. He don't want to share his current location. Here we have two possibilities. Either user allowed to visit the site or user can deny it. And based on two possibilities, we can have two different options here. If user allow to visit the site, the position call back will be ready. And if user deny it, then we have error call back. For now, I'm showing both the call backs. Here we have one position call back that is for positive case and the error call back for negative case. And you will see that pop-up is gone. Now for now let's go with only positive scenarios. Consider user click on allow to visit the site. And now we have position call back ready. Then it will follow the similar step. First it will go to task Q. If you see here it is going to the task Q. And now this position call back will wait in the task Q until event loop picks it. Now we have event loop that comes in action and it is active now and it will see we have a empty call stack. So it will pick this position call back and add that into call stack and the call stack quickly execute it. Once that execution is done the call stack will be empty now and user current location will be displayed in the console. Hope you are clear with second example. Now let's go with one more example and that will help you to understand a synchronous JavaScript in much better way. In third example we will go with two more web APIs and that is related to DOM and event. The example here is very simple. We will start with console.log. We will end with console and in between we just have one button in the browser. We will get that button reference by using document.getelement. get element by id and add event listener on it and when user click that button we will just console button clicked message very simple example and it will follow the similar approach but we just going with the different web APIs when JavaScript start executing the global execution context is added into the call stack and then we have a first line here we have console here. So console web API comes in picture and it will print start on the browser console. Then JavaScript C we are using document dot getelement by id. This is present from the DOM web API and which is used to get the button reference and then it will simply stored the reference of this HTML element into this button variable. Now we will move to the next line. Again we have that button and we are adding add event listener on it. This add event listener will be present from the event APIs and uh it will register a callback function in the web API environment. Here I'm using arrow function but now you can consider this as a named function with name call back. Important point here this call back is not executed yet. It is just registered. This will execute when user click on this button and we don't know when user will click on this button. So JavaScript will continue its execution and now it will go to next line. This is the last line of our script. So it is executed. it will print end in the console and this global execution context will be popped out of the call stack. So that is happening. We have call stack empty and end is printed here. Now we are done with the script execution and this call back function will sit in web API environment waiting for user to click on this button. So what will happen when user click on this button? This call back function is ready to execute. It simply comes into call back queue. So let's see here. User clicks on button. The call back function is ready for execute and it is come into the call back queue and the event loop will be active. Now it will see we have a empty call stack and we have something to execute in call back Q. So it will pick this task and add into the call stack. This task is added into the call stack. It will execute now. And once its execution is done, we have console.lo statement that is printed on console. And then we have a empty call stack. See here our function execution is completed. So we have empty call stack. We have empty call back Q and this button clicked will be printed on consoles. Hope you are clear with this third example as well. Till now we have seen three different examples. The first one is with set timeout. The second one is with Jolocation API and the third one is with user events. Even through they look different but underline they follow the similar approach. In every cases the call back is registered in the web API environment and once that call back is ready for execute it comes to call back queue and then event look picked it a call stack is empty and then it is executed. In simple word call stack execute all your code. Web APIs are used to connect with external word and they handle your async code through call back Q and then we have event loop that connects everything together. If you understood all these three examples and following along with me and get idea around how this flow work, you already mastered how a synchronous JavaScript works. But wait, we have few more things to discuss and those are very important. Till now everything looks quite straightforward. Task goes to web APIs. From web APIs it is going to call back Q and from call back Q it again comes to call stack. But when it comes to promises or fetch API call things work little differently and more interestingly to truly understand the difference now let's go with one more example in this example we will go with fetch API call and along with that we will discuss set timeout as well we will see how those things are differ from each other In this example, we are using three web APIs. The first one is console. The second one is timer and the third one is fetch. So all the three web APIs are listed here. The console is for console.log. Then timer is for set timeout and then fetch API for network request. And we know that initially our call stack is empty. And before executing the single line of code, JavaScript creates global execution context. And that execution context is added into the call stack. Now the script execution is started. We are on line number one. Here call stack C like this is console.log and this request is delegated to console web APIs and it will basically print that start on your console. On next line we have set timeout. So JavaScript again delegate this set time request to timer APIs. And we know that when we have set the timeout the call back is registered in the web API environment and attached with its timer. So in this case we have this particular call back and that is executed after 4 seconds. So this call back will be registered in the web API environment and the timer is attached to it. You can consider name of this call back as a CBT that is call back timer. Then JavaScript will not wait for anything like it will directly move to the next line. And now we have next web API that is fetch. We are making the API call for some dummy request here and it will make the network request and fetch the necessary data for us. This fetch will return promise and then we are attaching dot then to it. So call stack delegate this network request to web API. So you will see new call back is registered in the web API environment and I'm giving name as CBP that is call back promise and here browser started fetching data in the background. So we will move to the next line and we have last line of our script that is end. Once this line is executed our script execution will be completed. This end will be printed on console and this global execution context will be popped out of the call stack. So if you see here the global execution context is popped. Call stack is empty now and the end is printed on the console and our script execution completed here. Now at this point we have two call back registered in the web API environment. Right. The first one is CBT that is waiting for timer to finish and then we have CBP that is waiting for promise to resolve. Once promise is resolved this call back function will be ready for execution and once timer is finished this CBD function will ready for execute. Consider this API call is taking more time and meanwhile this 4 secondond timer is finished and we know what will happen in this case right this CBT function is ready for execution it is pushed into the call back Q then event loop see if we have empty call stack and it pick that function and that function is quickly executed this is simple and straightforward forward. We are clear with that now. But here we have now interesting question. What happen when that promise get resolved and which function that is CBT or CBP gets executed first? Now consider this API call is very fast. It will return us the result in few milliseconds. And in this case the promise is resolved and this CBP function is ready for execution. Still the timer is continue running and it needs to complete 4 seconds. So question is what will happen with this CBP function? Does it added to call back Q same as a timer or go API? No. This CBP function now goes into the different queue and that Q is microtask Q. Things are interesting right? This microtask Q is similar as a call back Q but having higher priority and uh when it comes to event loop event loop pick the task first from microtask Q and then it will go to call back Q. In this case, initially both the cues are empty. And now this CPP function is ready for execution. So it will directly go to microtask Q. It is waiting there. Then event loop comes in action. It will check if we have empty call stack. In this case, we have empty call stack. So it will pick that CP call back from microtask Q and add that into the call stack. And job of call stack is very simple. It will quickly execute it. And once executed we have data received printed on console. Simple clear, right? And meanwhile this CBT function still waiting this timer to complete. Right? Suppose this timer is completed after 4 seconds. Now this CBT function is ready for execute and it will follow its traditional path. It will go to call back Q. Now it is coming to call back Q. Again event loop comes in action and it will see we have empty call stack and it will pick this CBT function and add into call stack and call stack quickly execute it and inside set timeout will be printed on console and this is how things works together. Hope you are clear with that. The call back function attach to promise will follow the microtask Q approach and all other web APIs we discussed till now those are going to call back Q. Microtask Q is always having higher priority than the call back Q. Now understand one more scenarios. Till line number 10 our code is executed. the set timeout and fetch call back registered in the web API environment. But from line number 11, right, we have long running code here. Suppose we have large amount of code and call stack is now busy with that executing longunning task. While this call stack executing longunning task in the background, the API call will be made and this data will be fetched. So promise is resolved and now this CBP function is ready for execute. So it will follow its traditional approach and it will go to microtask. Still call stack is busy. It's doing its work. So this CBB function needs to wait in microtask Q because event loop will only pick task in the queue if call stack is empty. And in this case the call stack is continuously executing some synchronous longunning code. The call stack is continue working and meanwhile this 4 seconds also completed. This CBT call back is now ready for execute and again it will follow its traditional approach and it will come to call back Q. Now we have task in both the cues and meanwhile coil stack is still doing the execution of long running synchronous task. We don't know how much code we have. It could be millions of line of code right and call stack is currently busy with that. Suppose now this longunning task is completed. So code will move to the next line. This is the last line in our code. And uh once this line is completed this global execution context will be deleted from the call stack and this console.log end will be printed on console. If you see here call stack is empty now and end will be printed in console. And now event loop comes again in action. It will check if we have empty call stack. In this case yes. So first it will pick the task from microtask Q because it's having higher priority. So CBP call back will be picked by event loop and pushed into the call stack. Call stack quickly execute it. Once the execution is done, we have empty call stack and this particular string will be printed on console. Now event loop again check if the call stack is empty and if we have anything in microtask Q. Right now we don't have anything to execute in microtask Q. So it will go to call back Q and then it will pick this CBT call back and push that into the call stack for execution. Call stack quickly execute that CBT call back and inside set timeout will be printed on console. Now we have empty call stack and empty call back Q. And this is how things work. When we have very longunning task, the call stack first will finish all the synchronous code. And meanwhile we can have multiple task in microtask Q or call back Q. And once all the synchronous code execution is done, the task from the microtask Q and call back Q will be picked by event loop. And here again the higher priority will be given to microtask Q and then call back Q. This is how a synchronous JavaScript works. Hope you are clear with all the details. Now we have few more questions as we have two cues. One is call back Q or task Q and another one is microtask Q. Right? And microtask Q is having higher priority. So what all thing will go to microtask Q and answer is simple. There are only few things those will go to microtask q. The first thing any call back function attached to promises. It could be dot then dot catch or finally any call back function present in promise chaining will go to microtask. Second thing is mutation observer. The mutation observer is again the API provided by the browser in JavaScript that let you watch for changes in the DOM and then it will run the callback function when those changes happen in the DOM. Then we have a sync aait right so whatever code or the function body we have await keyword that is go to microtask Q and finally we have Q microtask. This is again one of the web API provided by the JavaScript and it will help you to run function as a microtask. So those four things will go to microtask Q and apart from anything any call back that we discussed till now all will go to call back Q or task Q whether it is a timer JO managing the events and any asynchronous operation everything will goes to task Q and understanding this difference is very important because when we have outputbased question understanding what things will go to microtask Q and what things will go to call back Q is very important based on that our output will be changes I hope you have solid understanding around the asynchronous JavaScript now how callstack works what are web APIs what is task Q or call back Q what is microtask Q what is event loop when event loop comes in picture and what different things will go to call back Q and microtask Q. Finally before ending this video let's understand one more very important concept and that is asked again in most of the interviews and that is starvation of function. We have two cues right. The one is call back Q and one is microtask Q. And event loop give higher priority to micro task Q. First it will finish all the task in microtask Q and then it will pick the task from call back Q. Suppose if event loop pick first task, right? The task one is now executed. Now call stack is empty. Again event loop will pick second task from the microtask Q that is task two. Now this task will go to call stack and it started execution. And what if this task two will create another task it is possible right? might be task two is having some API related code or it's using some mutation observer or it having Q task logic suppose this task two is executed and it created one more task that is task four now this task four will go to web API environment and might be it is quickly finishes making the API call right and this task 4 is now ready for execution Again this task four will come to microtask Q and meanwhile your task two is still executing. Now task two execution is completed and we have empty call stack and it will pick task three. Now the task three execution is started and what if task three will create another microtask. This is possible right? This could go in infinite loop. We don't know what will happen in this code right? And if create one more task that is a task five again it will come to microtask Q and this cycle will continue. In this case the event loop always give higher priority to microtask you right and then whatever task is present in the call back queue they need to stay for longer time and that is starvation of function. At the end this task is call back function right and these task are waiting in the call back queue for long time because we have multiple things in the microtask q and those are continue in the cycle and in this case this function needs to wait and this is called starvation of function. This is very important interview question and ask in most of the front- end interviews. You should be clear right when we have multiple things in microtask Q the call back Q will not get chance to execute. Suppose now this task three is completed and we have empty call stack. In this case the task four will get chance from microtask Q and once we have empty call stack and empty micro task Q then and then the task in the call back Q will be executed. Now task one is executed then task two will execute. Meanwhile if you get anything in microtask Q again that will get higher priority and then task three needs to wait until microtask Q will be empty. Here task two will be completed and then task three will get chance and once the execution stop our call stack and both the cues are empty now and this is how things work. Starvation of function very important concept. In our previous video, we already seen how exactly call stack will be visible in the browser. Right? We see how the global execution context or function execution context is added into the call stack. Right? But showing how callback Q or microtask Q or event loop works that is at least not possible in the browser till now. Those are internal things to the browser and handled internally and that is not exposed on the dev tool or we don't have any way to directly visualize it. Hope you are clear with all these details. Finally, I think that's all for this video. We have covered lots of interesting content and if you understood those properly you are able to crack almost every front end interview at least for a synchronous code changes. That's all for this video. Thank you for watching. If you are enjoying my content, I request you to like it. Please share this beautiful content with your friend so it will reach to more people. If you have any questions do comment me and I will answer as soon as possible. And finally subscribe to channel for getting latest video notification. Thank you for watching and see you in next one. Till now thank you. Bike.
Generated algorithmically for Search Engine
Indexing.