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.
2 Answers 2
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
asyncfunction'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:
- Logging that function
runexecution started - Attaching an event to
setTimeoutwhich will be finished in ~2 seconds - Log into console that
setTimeoutstarted - Creating promise with
getPromisefunction and withawaitkeyword wait tillresolve - In ~2 seconds
setTimeoutlogs that it has been finished - In ~3 seconds from
Promisetheresolvefunction called runfunction finishes its execution afterresolveand logging.
I hope that helps you understand this portion of the code.
Comments
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();
setTimeoutis to do something later in time, hence asynchronous.1; Print2after 2 seconds; Print3" 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.