Skip to content
Advertisement

async function javascript is not running in background?

console.log("1");
  console.log("2"); 
async function a() {
    for (let i = 0; i < 1000000000; i++) {}
    for (let i = 0; i < 1000000000; i++) {}
  }
  a().then(() => console.log("in then"));

  console.log("3!");

This output I want is this 1 2 3! in then

but the async function behaves synchronously and does not let the 3! print until after the long loops are done executing. I thought if the async keyword is used, it runs the function inside in the background? I basically want the 2 long loops to run in the background. Just trying to understand async and await. Thanks.

Edit: could someone tell me why this also works synchronously??

  console.log("2");

  function lag(resolve) {
    for (let i = 0; i < 1000000000; i++) {}
    for (let i = 0; i < 1000000000; i++) {}
    console.log("in lag");
    return resolve;
  }
  async function a() {
    // console.log("its done");
    let a = await new Promise((resolve, reject) => lag(resolve));
  }
  a().then(() => console.log("in then"));

  console.log("3!"); ```

Advertisement

Answer

There is nothing about async functions (or promises) that makes anything run in the background. They don’t create a new thread or anything like that.

An async function is synchronous until the first await or return. Since your function doesn’t have any await or return, it’s fully synchronous.

The purpose of promises is to observe the completion of something that’s already asynchronous, such as the browser’s loading things via HTTP, or a timer. The purpose of async functions is to have syntax for using promises that lets us write the logical flow of the code rather than writing callback functions. Neither of them makes anything asynchronous, or moves things to a different thread.

If you want to run something in the background, you can create a worker thread and exchange information between it and the main thread via messaging. On browsers it’s web workers. In Node.js it’s the worker threads module.

In your question and in comments on the answer you’ve talked about how an async function seems to wait for an asynchronous task to complete. And indeed, the logic of the function does. But that’s really syntactic sugar for using promises (really, really good syntactic sugar, IMHO). Let’s look at an async function:

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

async function example() {
    // The function starts out synchronous, so that it can
    // start whatever inherently-asynchronous thing it does
    // (like calling `fetch`).
    console.log("[example] This is synchronous");

    // When execution reaches the first `await` or `return`,
    // the `async` function returns a promise. The synchronous
    // part of its work is now complete.
    await delay(10);

    // This code runs later, when/if the promise from `delay`
    // is settled.
    console.log("[example] This is asynchronous, but still on the main thread");

    // If you `throw` in an `async` function, it rejects the `async`
    // function's promise.
    if (Math.random() < 0.5) {
        throw new Error("Error thrown by `example`");
    }

    // The "return" value of an `async` function is the fulfillment
    // value of the promise the `async` function returned
    return 42;
}

console.log("[top] Calling `example`...");
const promiseFromExample = example();
console.log("[top] Back from calling `example`. Waiting for its promise to settle.");
promiseFromExample
.then((value) => {
    console.log(`[top] The promise from `example` was fulfilled with the value ${value}`);
})
.catch((reason) => {
    console.log(`[top] The promise from `example` was rejected with the rejection reason ${reason.message}`);
});
.as-console-wrapper {
    max-height: 100% !important;
}

Run that a few times so you see both a fulfillment and a rejection (each run has a 50/50 chance). Nothing in that code runs anywhere but the main thread, it’s just that with await, the logic in example can wait for a promise to settle. The promise from delay lets us observe the completion of the timer, then example awaits that completion before continuing its logic.

The key things are:

  • Promises don’t make anything asynchronous¹
  • Promises and async functions don’t move anything off the main thread
  • async functions always return promises
  • The code in an async function runs synchronously until the first await or return
  • The promise from an async function gets fulfilled with the return value of the function, or rejected with any error that occurs in the function

¹ Okay, there’s one caveat to that: If you use .then or .catch (or .finally) to hook up a callback to a promise, that callback will always be called asynchronously, even if the promise is already settled.

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement