0

This question might sound weird but to my understanding, the asynchronous code should execute independently from the main thread. Look at this code:

async function async() {
    while (true) {

    }
}

async()
console.log('test')

While loop wouldn't block this code if the whole function was asynchronous and "test" should be logged to the console, but it doesn't happen. Why it is this way?

Gieted
  • 835
  • 6
  • 21
  • 3
    I think you may have a fundamental misunderstanding of what an `async` function is. If your function does not include any `await` statements, and if it does not return a Promise somehow, then it's just a plain function. – Pointy Apr 17 '19 at 19:46
  • 6
    async != multi threaded. – Daniel A. White Apr 17 '19 at 19:46

2 Answers2

1

Asynchronous does not mean that the code is running in a different thread. Asynchronous execution is cooperative multitasking within the same thread. Functions yield execution back to the event loop through await or by finishing their execution, and the event loop will continue their execution/execute callbacks upon certain events (e.g. network request having finished, or a setTimeout timer having completed). It's still entirely possible for one function to hog the thread using an infinite loop.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • I think I get it. So the only reason why async functions exist is to cooperate with threads. The async function returns a promise, which could be resolved in a different thread, which can be used to define additional callbacks after promise will be resolved. Am I right? – Gieted Apr 17 '19 at 20:17
  • 1
    @PawełKiełb No, JavaScript only has a single executing thread. The resolving is happening on the same thread, it might just happen at some point in the future (i.e. asynchronously) – pushkin Apr 17 '19 at 20:19
  • @deceze♦ My bad, but still Node's Event Loop is very similar to threads and in fact, can make two functions being executed simultaneously. – Gieted Apr 17 '19 at 20:37
  • @PawełKiełb This is all just based on *callbacks*. Simple example: a network request. Your Javascript code tells the “backend” API to make a network request, and *call a specific function with the result*. While the network request is waiting for a response, the Javascript engine is free to do other things. Once the response arrives, the callback function is called and will end again, at which point the engine is free to do other things again. That’s basically async in a nutshell. The `async`/`await` syntax is just syntactic sugar on top of this simple principle. – deceze Apr 17 '19 at 20:40
  • @PawełKiełb No, two functions will never execute simultaneously in Javascript (unless you explicitly invoke a new thread). – deceze Apr 17 '19 at 20:41
  • deceze♦ Your are right! Thanks for the explanation! – Gieted Apr 17 '19 at 20:47
1

In Javascript, async functions are only asynchronous, all code still executes on a single thread. (The exceptions to this is when you use something like threads in Node or web workers in the browser, see the links for more info on that.)

To illustrate what this means, let's define two sample functions:

function halts() {
  const start = Date.now()
  while (Date.now() < start + 2000);
}

function resolves() {
  return new Promise((resolve) => setTimeout(resolve, 2000));
}

The first function will block the thread for roughly 2 seconds, returning nothing, the second function will return a promise that will resolve after a similar period of time.

When you're using these functions, the crucial difference is that when calling the first one, all execution blocks up until the function completes, since everything is running on a single thread:

function halts() {
  const start = Date.now()
  while (Date.now() < start + 2000);
}

const before = Date.now();
halts();
const after = Date.now();
console.log(`execution halted for ${after - before}ms`);

The difference when using asynchronous operations (regardless of whether you use promises or async-await for the implementation) is that you can allow the main thread to take on other work until you wait, for example, for a network request to complete.

function resolves() {
  return new Promise((resolve) => setTimeout(resolve, 2000));
}

const interval = setInterval(() => {
  console.log('ping');
}, 500);

const before = Date.now();

resolves().then(() => {
  clearInterval(interval);
  console.log('promise resolved');
});

const after = Date.now();
console.log(`execution halted for ${after - before}ms`);

Notice how the second example continues with the execution of the rest of the code immediately, instead of halting everything. The async operation isn't done on a separate thread, it's simply deferred for later on the same thread.

For a more technical explanation, Deceze's answer is a good short summary, this video by Jake Archibald is a good general overview as well.

Etheryte
  • 24,589
  • 11
  • 71
  • 116