What Are Asynchronous Functions in JavaScript? What Is "Async" and "Await" in JavaScript

How does javascript async/await actually work?

You have to read the quoted part slightly differently:

An async function can contain an await expression that pauses the execution of the async function

Just the async function itself pauses execution, the function that called it goes on then.

If you think of a synchronous callstack, what happens is that the asynchronous functions context gets popped of, and stored somewhere else:

 stack: [init] -> [async] fun1 -> sleep -> setTimeout
// The promise gets returned from sleep
stack: [init] -> [async] fun1
// The async function gets popped of
stack: [init]
hidden: [async] fun1
// synchronous execution ends
stack: -
hidden: [async] fun1
// the timer triggers, the promise gets resolved
stack: setTimeout callback
hidden: [async] fun1
// synchronous execution ends
stack: -
hidden: [async] fun1
// the promise resolves, the async fun1 context gets moved onto the stack
stack: [async] fun1

It seems fun1 returns at the "await" line

Yes, exactly. In that moment it returns a promise, that resolves when the async function returns (after it continued execution somewhen).

And it seems I never get the return value of fun1("returnfromfun1").

You can get it when the promise resolves:

  fun1().then(result => console.log(result));

Why is async required to call await inside a JavaScript function body?

There are three reasons the async keyword exists:

  1. In ECMAScript language versions prior to 2015, await was not a keyword. Marking a function async provides a syntactic "bailout" to indicate a breaking change in the language grammar within the body of the function.

    This is the most important reason. Without the async keyword, all programs written in ECMAScript 5 or older would no longer work if they used the await keyword as a variable (in fact this was done intentionally in some cases as a polyfill before async/await was standardized), since that would cause a breaking change without the addition of async to the specification. Because of this, async is syntactically necessary to avoid breaking changes to the language.

  2. It provides a convenient marker for parsers, avoiding an infinite look-ahead in order to determine whether or not a function is asynchronous.

    This makes parsing more efficient, which is appealing for both ECMAScript implementers and developers, though this reason alone does not make async strictly necessary to the syntax.

  3. async also performs its own transformation on the function, which is done regardless of whether or not the await keyword is present in the body.

    Consider the following two functions:

    function foo() {
    if (Math.random() < 0.5) {
    return 'return';
    } else {
    throw 'throw';
    }
    }

    async function bar() {
    if (Math.random() < 0.5) {
    return 'return';
    } else {
    throw 'throw';
    }
    }

    async performs the following transformation of function bar():

    function bar() {
    return new Promise((resolve, reject) => {
    try {
    resolve((/*async function bar*/() => {
    if (Math.random() < 0.5) {
    return 'return';
    } else {
    throw 'throw';
    }
    })());
    } catch (reason) {
    reject(reason);
    }
    });
    }

    Those familiar with promises will recognize that we can simplify the above since the Promise constructor executor function will implicitly reject if it throws an error synchronously:

    function bar() {
    return new Promise((resolve) => {
    if (Math.random() < 0.5) {
    return resolve('return');
    } else {
    throw 'throw';
    }
    });
    }

Asynchronous Javascript Confusion

The key thing to understand is that async functions are syntactic sugar for using promises. Neither async functions nor promises make anything happen in the background. They let you wait for and react to things that already happen in the background (like a timer or an HTTP operation completing).

An async function is synchronous up until the first await or return. (That's so it can start whatever asynchronous process it then waits for.) At that point, it returns a promise that will be fulfilled or rejected depending on what happens to the promise being awaited and/or what you return.

await pauses the logic of the function until/unless the promise being awaited settles. (If you use await value where value isn't a thenable [a promise-like thing], you're effectively doing await Promise.resolve(value).)

You haven't shown any contents of the asyncFuncX functions, but unless they await something, they're fully synchronous.

You may find my answer from a couple of days ago useful as well.

What are the advantages of using async/await?

It can be considered to be not actually synchronous. When you await something that is async, it gets added to a microtask queue. It does not run on the main thread, meaning other things can occur (click events, rendering, etc.)

Here is a fantastic talk that can explain it in further detail
https://www.youtube.com/watch?v=cCOL7MC4Pl0

await/async are often referred to as syntactic sugar, and let us wait for something (e.g. an API call), giving us the illusion that it is synchronous.



Related Topics



Leave a reply



Submit