1

I have problem understanding how async function work in JavaScript. Let's take the code below:

async () => {
      console.log(1);
      setTimeout(() => console.log(2)
        , 2000)
      console.log(3);
}

I would expect that invocation of synchronous function inside async should block thread before executing further code. So I'd expect to get 1 -> 2 -> 3 instead I'm getting 1 -> 3 -> 2. Can't find explanation why it's happening and how to block thread to receive output 1 -> 2 -> 3. I'm using Node 12 with serverless framework.

3
  • 2
    The sole purpose of setTimeout is to do something later in time, hence asynchronous. Commented Jan 11, 2020 at 12:41
  • 1
    The instructions you've given are literally "Print 1; Print 2 after 2 seconds; Print 3" That's exactly what you get - 1 -> 3-> 2 second wait -> 2. And async functions also are...async. Halting the thread because you've called a synchronous function in an async one also makes no sense. You are better off reading this, this, and this then asking about a concrete problem. Commented Jan 11, 2020 at 12:49
  • Ok that's my bad. I thought setTimeout is synchronous. My actual issue is with processing stream with github.com/request/request inside async AWS lambda function. Somehow when I invoke it locally everything works fine but in cloud it's not waiting for stream to be closed. But that is another topic. Thanks for your time Commented Jan 11, 2020 at 13:10

2 Answers 2

1

async itself won't wait until execution of setTimeout finished as you expect. As you can read from the documentation - find here for async:

An async function can contain an await expression that pauses the execution of the async function to wait for the passed Promise's resolution, then resumes the async function's execution and evaluates as the resolved value.

Just built a quick example to see the difference between async and await solution and just using setTimeout as it is in your example.

Consider the following example:

const getPromise = async () => {
  return new Promise((resolve) => {
    setTimeout(resolve, 3000);
  });
}

const run = async () => {
  console.log('run started');
  setTimeout(() => console.log('setTimeout finised'), 2000);
  console.log('setTimeout started');
  const promise = await getPromise();
  console.log('Promise resolved');
  console.log('run finished');
}

run();

Steps explained:

  1. Logging that function run execution started
  2. Attaching an event to setTimeout which will be finished in ~2 seconds
  3. Log into console that setTimeout started
  4. Creating promise with getPromise function and with await keyword wait till resolve
  5. In ~2 seconds setTimeout logs that it has been finished
  6. In ~3 seconds from Promise the resolve function called
  7. run function finishes its execution after resolve and logging.

I hope that helps you understand this portion of the code.

Sign up to request clarification or add additional context in comments.

Comments

1

I would expect that invocation of synchronous function inside async should block thread before executing further code.

It does

So I'd expect to get 1 -> 2 -> 3 instead I'm getting 1 -> 3 -> 2.

setTimeout is not synchronous. It very explicitly is for queuing up a function to run later, after some time has passed.

Can't find explanation why it's happening and how to block thread to receive output 1 -> 2 -> 3.

You can't per se.

The closest you could come would be to replace setTimeout with a loop that runs around in circles until some time has passed… but that would be awful (it would lock up the UI for starters).

If you want to just run the three logs in order, then replace setTimeout with something that returns a promise and then await it (which would put the async function to sleep and let any other code continue to run until the promise resolved).

const timeout = function() {
  return new Promise(function(res) {
    setTimeout(() => {
      console.log(2);
      res();
    }, 2000)
  })
};


const x = async() => {
  console.log(1);
  await timeout();
  console.log(3);
}

x();

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.