preface

It is well known that JavaScript is single-threaded, but it is inevitable that JavaScript also needs to perform asynchronous tasks, such as the following example

function foo() {
    console.log("first");
    setTimeout(( function(){
        console.log( 'second' );
    }),5);
}
 
for (var i = 0; i < 1000000; i++) {
    foo();
}
Copy the code

In the example above, the results of the execution will all print first and then second, instead of alternating. In this process, it is obvious that concurrent asynchronous tasks are happening.

JavaScriptWhy single threaded?

As a Java programmer, one of the first reactions to learning that JavaScript is single-threaded is to wonder why a language is designed to be single-threaded. Why can’t it use multithreading for efficiency?

The single thread of JavaScript, relative to its purpose. As a browser scripting language, JavaScript’s primary purpose is to interact with users and manipulate the DOM. This means that it has to be single-threaded, which can cause complex synchronization problems. For example, if there are two threads of JavaScript at the same time, one thread adds content to a DOM node, and the other thread removes that node, which thread should the browser use?

So, to avoid complexity, JavaScript has been single-threaded since its inception, and this has been a core feature of the language and will not change.

JavaScriptHow to implement asynchrony?

Now that we know why JavaScript is single-threaded, how can it be asynchronous? JavaScript’s asynchronous capabilities are primarily provided by the runtime environment

JavaScriptThe operating environment of

JavaScript RuntimeThat isJavaScriptWhere the code runs. Such asJavaScriptCan be found inchromeCan also be executed innodeIn the implementation,chromewithnodeAre allJavaScript Runtime

JavaScript Runtime includes JavaScript Engine and WebAPI. JavaScript Engine converts JavaScript we write into more efficient machine code to achieve better performance. JavaScript in Chrome is handled by the V8 engine. V8 engine mainly consists of two parts: memory heap and execution stack

  • Memory heap: Used for allocationJavaScriptMemory used by the program.
  • Execution stack: In the execution stack, yourJSThe code is read and executed line by line.

In addition to the engine, JavaScript Runtime also provides WebAPI for JavaScript code to call, WebAPI provides network request, timer, event listener, etc. Because JS Runtime is not single threaded, it holds a thread pool, Therefore, code in WebAPI runs on other threads, which naturally provides asynchronous capability

Event loop mechanism

  • JSIt is divided into synchronous tasks and asynchronous tasks. Synchronous tasks are executed on the main thread, forming an execution stack
  • Code calls in the stackWebAPIWhen asynchronous tasks are completed, they add various events to the event queue
  • When the code on the stack finishes executing, it reads the events in the event queue to execute those callbacks
  • The execution stack and the task queue do this, which is the event loop mechanism

It is important to note that once all of the execution stack (JS engine idle) at this time synchronization task has been completed, the system will read the task queue, will be able to run the asynchronous task are added to the executable stack So the setTimeout setting time is not accurate, may push it to the event list, the main thread is not free, are performing other code, So there’s an error.

conclusion

JavaScript is essentially a scripting language that runs in the browser and is designed as a single-threaded language for simplicity and to avoid synchronization problems when manipulating the DOM. The asynchronous capability of JavaScript is provided by the runtime environment. Through WebAPI and event loop mechanism, single-threaded JS can also perform asynchronous tasks.

The resources

JavaScript runtime mechanism details: The Event Loop is a threaded, non-blocking, asynchronous, and concurrent language