I couldn't understand the execution order of the two codes below.
async function main(test)
{
while(1) console.log(test);
}
main("a");
main("b");
This code above logs infinite "a".
async function main(test)
{
while(1) await console.log(test);
}
main("a");
main("b");
While this code above logs infinite "a" and "b".
I wanted to understand async/await better but this behaviour above made me confused. Like how are those log functions handled by event loop?
CodePudding user response:
An async
function runs synchronously until the first await
, return
, or implicit return (the code falling off the end of the function). That's so it can start the asynchronous process that it will later report the completion of (by settling the promise it returns). So your first example logs a
forever because that's done by the synchronous part of the first call to main
; execution never reaches the second call to main
.
Your second example introduces asynchronousness by adding await
(it doesn't matter that what await
is awaiting isn't a promise [console.log
returns undefined
]; it gets wrapped in one). That means that the first call to main
runs synchronously until after the first console.log
, then stops and returns a promise while it waits for the promise wrapped around undefined
to settle.¹ That allows the second call to main
to go forward, doing the same thing. At that point, the code making the calls to main
is complete and any pending promise callbacks can be executed. The first pending promise callback is for the await
in the first call to main
, so that call does another loop iteration; the second pending promise is for the await
in the second call to main
, so it does another loop iteration; and so on, and so on, and so on.
You mentioned "concurrency." The two calls to main
in your second example do run concurrently but are not multi-threaded; instead, they each alternately get access to the one main thread briefly until their next await
. JavaScript works on a model of one thread per "realm" (loosely, per global environment). So you don't have to worry about threading issues like reordered operations or stale caches like you would in a multi-threaded environment (unless you're using shared memory, but you aren't in that code); there's only one thread.
¹ Technically, the promise is already settled in this case before await
starts awaiting it (because it's just a promise wrapped around undefined
), but when you attach to a promise, it never triggers your code synchronously, even if the promise is already settled.
CodePudding user response:
Using Asynchronous functions within Javascript usually resolves data that is not readily available. Examples include calling from a database and scraping web pages for data.
The code provided endlessly loops because there is no end to the said loop (while
). In the context of the code provided, while(1)
will always remain true, as there is no condition to state otherwise. In practical use, loops are designed to cease when a condition is met.
Here's a basic example of using a while
loop sourced from MDN Docs covering break
let n = 0;
while (n < 3) {
n ;
}
console.log(n);
// expected output: 3
To better understand asynchronous programming within Javascript, I highly recommend the MDN Docs on async functions.
To answer your question regarding console logging's interactions with await
: JS will 'freeze' the script when it reads an await
and work on completing its defined actions, then returns to read the following line. In the context of the code, Javascript is doing its job. It circles back to a lack of a break
or condition for the loop.