Why isn't Javascript async function immediately returning?

There a are a couple of reasons for what you're seeing:

  1. An async function is synchronous up until its first await or return, so the entire function runs before returning in your case.

  2. Busy-waiting isn't asynchronous.

  3. test needs to use await if it's going to wait for intense to complete before continuing.

  4. Moving something into a promise doesn't take it off the thread. The only way to do that in most JavaScript environments (including browsers) is to use a Worker thread (MDN, Node.js docs — Node.js has had Worker since ~v10.5, and while it's still marked "experimental" the main parts of the API should be fairly stable as they're drawn from the web worker standard API).

It's important to remember that promises don't make anything asynchronous¹, they provide a means of observing the result of something that's already asynchronous.

Here's an example using setTimeout for the asynchronous part that help you understand these better:

function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function intense(value) {
    console.log("intense(" + value + ") - This is synchronous");
    await delay(100);
    console.log("intense(" + value + ") - This is asynchronous, because it's after `await`");
}

async function test(){
    console.log("Print 1");
    intense(1);       // <== WITHOUT await
    console.log("Print 2");
    await intense(2); // <== With await
    console.log("Print 3");
}

test();
.as-console-wrapper {
  max-height: 100% !important;
}


¹ There's one small caveat to that: The handler you pass to then, catch, or finally will always be called asynchronously, even if the promise you're calling them on is already settled. That's literally the only thing that promises actually make asynchronous.


so it would return a promise immediately and continue work asynchronously.

No it would not. The callback passed to the Promise constructor is called immeadiately. What is async is the process of calling resolve or reject later on, and how .then chains get called back somewhen.

However it isnt async in the sense that the code runs on another thread or gets deferred, that won't happen as JS itself is executed in a single thread*.

 console.log(1);
 const promise = new Promise((resolve, reject) => {
  console.log(2); // gets executed immeadiately 
 });

 promise.then(() => console.log(4)); // < Promise resolve asynchronously
console.log(3);

*If you plan to do really "intense" work, it might be benefitial to do that in another thread (see WebWorker in browsers and child_process.spawn for NodeJS).