Written by Kirill Bychkov for UppLabs.
JavaScript is easy when all you need is a simple working interface. The problems begin when the interface becomes more complex. Here you need to have a deeper understanding of JavaScript. It is important that even a large and complex interface remains fast and responsive. Responsiveness is usually achieved through the use of asynchronous functions. This means that you can let your code do several things at the same time without stopping or blocking the main thread.
In this article, I will try to tell you as simply as possible about the work of asynchronous in JavaScript. At all interviews in my life, I have been always asked this question. When you start learning JS, it can seem daunting but in reality, everything is much simpler.
How does the Event Loop work?
Event Loop is one of those things that every JavaScript developer encounters in one way or another. JavaScript provides a concurrency model based on an event loop, which executes the code, collecting and processing events, and performs queued sub-tasks.
I think it's not difficult to guess what sequence these logs will be called in. Let's check.
But let's take a look at what's going on under the hood. In the example, I am using this helpful site
When the program starts, it runs through the lines of code. When an asynchronous operation comes across, the interpreter throws this operation into a Call Stack. In the stack, it begins to look like a certain set timeout and as a browser API. Then it throws out the set timeout and registers some anonymous function in the web APIs, which will be executed when the browser completes the set timeout after 5000 seconds. Next, the anonymous function enters the callback queue. An endless loop runs in the queue, which runs over its elements, and if it detects that the function is ready, it throws it back into the call stack and executes.
Thus, we do not block the work of the code. We are talking not only about set timeouts but also about other asynchronous operations, such as event listeners that work along with the server.
But what happens if 0 is passed as the second parameter to the timeout set? Exactly the same. Let's see.
The browser will still drop the function into the web API, and the program will continue to work.
Let's also take a look at how the event listener works.
The event listener, as mentioned above, is also an asynchronous event and goes to the web API. You now understand the importance of unsubscribing from listening to events. You can read more details here
Macro tasks
Let's take the same event example and try to click the button a few times.
We see a queue of events. This is the macro task callback queue, a v8 term. Tasks from the queue are executed according to the first-in-first-out rule.
Let's note two details:
- Rendering of the page never happens during the execution of a task by the engine. It doesn't matter how long the task takes. Changes to the DOM are rendered only after the task is completed.
- If the task takes a very long time and the browser cannot perform other tasks or process user events. So, sometime later the browser offers you to "kill" the long-running task. This is possible when the script contains a lot of complex calculations or an error leading to an infinite loop.
Micro tasks
We could see the micro tasks in the last example. When the macro task is executing, the functions from it are placed in the call stack. The new macro task does not start its execution until the micro tasks have finished there. If you need more examples, you can check here.
Conclusions
Thanks to JavaScript, we can write asynchronous applications without thinking about multithreading like data integrity and data consistency. If we are performing an operation that takes time, such as querying a database and using the results to fill the templates, it is better to push them out of the main thread and execute the task asynchronously. We compensate for these benefits with a huge number of callbacks, and constant loss of context.
Depending on the specifics of the task, it may turn out that you will be using async/await, callbacks, or some mixture of different technologies. In fact, the answer to the question which asynchronous development methodology to choose depends on the specifics of the project. If a certain approach allows you to solve a problem using readable code that is easy to maintain and other team members can easily understand, then this approach is what you need!
Now you can use callback, promises or async / await with understanding how it works in the browser :)
I hope this article was helpful for you. You can also find more useful information on our blog.
Top comments (6)
Well put article, async is so important for UX. On the subject, if you have long running Javascript jobs that might mess up frame rates - such as big sorts or filters etc that happen on the client side, then you can also make those async using my js-coroutines library. In this way you can use the techniques described here to make client side processing silky smooth too.
Thanks!
Definitely worth taking a look at Philip Robert’s talk on the event loop
youtu.be/8aGhZQkoFbQ
Thanks!
Thank you for sharing this! It helps :)
Happy it helped! Thanks for the comment)