📜 ⬆️ ⬇️

Asynchrony in JavaScript: A guide for those who want to understand

image


JavaScript is easy to write. It is enough to take a couple of libraries or a fashionable framework, read an uncomplicated tutorial and that's it - in a couple of hours you have a simple, working interface.


Problems begin when the interface becomes more complicated. Here, without a deep understanding of JavaScript is not enough. It is important that even a large and complex interface remains fast and responsive. Responsiveness is usually achieved through the use of asynchronous functions. Let's try to figure out how asynchrony works in JavaScript.


There is no multithreading in JavaScript. In spite of the fact that we can already fully use webworkers , one cannot change the DOM or call the methods of the window object. In a word, not multithreading, but sheer disappointment.


The reasons for such restrictions are clear. Imagine that two parallel threads are trying to race to change the same node in the DOM with an unpredictable result. Submitted? I also felt uneasy.


image


With the DOM tree, working in the same thread to ensure the integrity and consistency of the data, but how to program the interface with a single thread? After all, the very essence of the interface is in asynchrony. This is what invented asynchronous functions. They are not executed immediately, but after the occurrence of the event. Interestingly, these functions are not part of JavaScript engines. Calling setTimeout on a pure V8 results in an error, since there is no such function in V8. Then where does setTimeout or requestAnimationFrame or addEventListener come from?


Asynchrony inside


The JavaScript engine looks like a meat grinder, endlessly grinding operations that are consistently taken from the call stack (1). The code runs linearly and sequentially. You cannot delete an operation from the stack; you can only interrupt the thread of execution. The thread of execution is interrupted if you call something of type alert or "exception".


image


Each operation contains a context - a certain area of ​​memory from which data is available. Contexts are located in memory as a tree. Each leaf in the tree has scopes that are defined in the parent branches and at the root (global scope). Functions in JavaScript are data, they are stored in memory as data, and therefore are passed as variables or returned from other functions.


Asynchronous operations are performed not in the engine, but in the environment (5.6). (As forgotten suggested, this is not quite true: we can immediately put the function in the call queue from the call stack and thus the clean engine will also work asynchronously)
Environment - add-on engine. NodeJS and Chrome for the V8 engine and Firefox for Gecko. Sometimes the environment is also called the web API.
To create an asynchronous call, a link to the function is passed to the web API, which will be executed later or not at all.


The function has its own context or its own memory region (3), in which it is defined. The function has access to this memory area and to all parents of this memory area. Such functions are called closures. From this point of view, all functions in JavaScript are closures, since they all have context.


Web API and JavaScrtipt engine work independently. The Web API decides at which point the function moves on to the call queue (2).


Functions in the call queue fall into the JavaScript engine, where they are executed one by one. Execution occurs in the same order in which the functions are queued.


The environment itself decides when to add the code transferred to it to the call queue. Functions from the queue are added to the execution stack (executed) no earlier than the call stack finishes working on the current function.
Thus, the call stack works synchronously, and the web API is asynchronous.


It is very important! The developer does not need to control the parallel access to resources, the asynchronous work for him is performed by the environment. The environments determine the differences between the browser and node.js, because we write network applications to node.js or access the hard disk directly, and from Chrome we intercept button clicks using the same engine.


You cannot cancel individual operations in the call queue. This is done in the environment (removeEventListener - as an example).


Examples


You can load the call stack so that it runs indefinitely and the next function in the call queue does not call. Try, for example, to run this code.


document.addEventListener('click', function(){ console.log('clicked') }); while(true){ console.log('wait'); } 

The click handler will not work, and an infinite loop will load the computer's processor. The tab will hang;)


Here is another example .



A click will cause a “heavy” function to calculate. After the click, start is written to the console, at the end of the function execution - end. Performing a function on my laptop takes a few seconds. As long as the function is executed, the square blinks. This means that the animations in CSS are executed asynchronously to the JavaScript code.


But what will happen if you change the size instead of opacity?



The square will hang for the duration of the function. The fact is that the CSS height property refers to the DOM. As we remember, the DOM can only be accessed from one thread, so that there are no problems with parallel access.


We conclude that for animation it is better to use properties that do not change the DOM (transform, opacity, etc.). And all the hard work in JavaScript is best done asynchronously. Like this.



The code is written for clarity and on the knee, in combat is not recommended . We divide a large piece of work into small ones and perform it asynchronously. In this case, the interface is not blocked. For such calculations, you can use web workers.


Conclusion


Thanks to JavaScript, we write asynchronous applications without thinking about multithreading: integrity and consistency of data. For these benefits, we pay a huge number of callbacks, blocking the main thread and constant loss of context.


I will tell you about how to deal with the latter problem next time.


')

Source: https://habr.com/ru/post/302896/


All Articles