sajad torkamani

A JavaScript engine (like V8) is single-threaded

When you hear that JavaScript is “single-threaded”, it means that JavaScript engines like Chrome’s V8 only execute a single sequence of JavaScript code at one time – using one main thread and one single call stack.

This means that if a given function from your application is running, no other code from your application is executed at the same time on another thread. The JavaScript engine can only operate a single thread at a time.

This is different from other languages like Java or Golang where a single program can spawn multiple threads, each with their own call stack, and able to run in parallel on multiple CPU cores.

But when paired with a browser or Node.js, JavaScript effectively becomes multi-threaded

JavaScript engines typically operate within a host environment like a web browser or Node.js which are multi-threaded environments.

So even though a JavaScript engine is single-threaded (can only spawn a single thread and run a single piece of code at one time), they work together with the host environment to effectively do multiple things at once (multiple threads run, each able to run different code in parallel)

For example, consider an XHR request made by code like this:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>JavaScript engine and browser</title>
  </head>
  <body>
    <h1>Hello</h1>

    <script>
      console.log('hello')

      const xhr = new XMLHttpRequest()
      xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts/1')
      xhr.onload = () => console.log(xhr.responseText)
      xhr.send()

      console.log('hello again')
    </script>
  </body>
</html>

Here’s what happens:

  • The JavaScript engine executes console.log('hello')
  • The JavaScript engine executes the xhr.open('GET', 'https://jsonplaceholder.typicode.com/posts/1') code. The browser provides the XMLHttpRequest API so when the xhr.open(url) method executes, the browser spawns a new thread and executes the network request in a separate thread outside the JavaScript engine’s main thread.
  • This allows the JavaScript engine to immediately move onto the console.log('hello again') statement. Suppose this network request took 2 seconds to complete. In this interval, you could have two threads running for your application: (1) the JavaScript engine’s main thread which executes your application code and (2) the browser thread executing the network request.
  • Once the browser has finished fetching the network request, it’ll add the callback listener from xhr.onload = () => console.log(xhr.responseText) to the callback queue so that the JavaScript engine’s event loop can pick it up when it has capacity. The host environment provides the event loop and the callback queue as a means of allowing the JavaScript engine’s main thread to use the results of operations executed in its own threads (things like network responses or a file read operation).
Tagged: JavaScript