Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Syntax question: Why is it necessary to define a function as async in JS?

It’s a simple question. We have the await keyword which allows the function execution to return a result before continuing. Of course you can use promises in the same way, but I’m specifically interested in async in this question.

An async function would appear in the following context.

const funcA = async newValue => {
    await connection.query(`UPDATE t SET field = ?`, [newValue])
    .catch(error => console.log(error));

    const valueA = await connection.query(`SELECT t.field FROM t LIMIT 1`)
    .then(([results, fields]) => (results?.[0] ?? null))
    .catch(error => console.log(error));

    console.log(valueA.field);
};

funcA("test");

A similar method of executing this without async would be

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

const funcA = newValue => {
    connection.query(`UPDATE t SET field = ?`, [newValue])
    .then(() => connection.query(`SELECT t.field FROM t LIMIT 1`))
    .then(([results, fields]) => (results?.[0] ?? null));
    .then(valueA => console.log(valueA.field))
    .catch(error => console.log(error));
};

funcA("test");

Now ignoring the practicality of this example code, and just focusing on the functionality, why do we need to use the async keyword before defining the function at all? Why not allow await in every function. The second example could have the async keyword but it wouldn’t work any differently because promises work the same in both contexts. Couldn’t we just eliminate the async keyword entirely?

I’m certain I must be missing something here but I don’t know the reasoning behind it.

>Solution :

OK this should not be taken as an authoritative answer. More like a folk tradition answer.

When code calls a function the way our grandparents called functions:

let x = f();

the function is invoked, it does what it does, and its return value is assigned to x.

Now let’s talk about an async function. Such functions are intended to help deal with the problem of sequencing calls to asynchronous operations. Formerly, that required constructing chains of .then() and callbacks, and .catch() for exceptions. That works, but it’s confusing and error-prone.

What async and await provide is an abstraction around handling that kind of Promise sequence of operations. Underneath, the Promise mechanism still does the same thing. A way to think about it (that is not entirely accurate) is that the await operator turns the code that follows it into a .then() callback for you.

Because a single async function may have many await calls internally, when it is called with await from some context, there we have to handle the fact that the single call may return Promise after Promise:

const af = async function() {
    let val = await a();
    val = await b(val);
    val = await c(val);
    return val;
}

Each await inside the async function will return a Promise. But consider calling af:

    let foo = await af();

To evaluate that, the three Promise objects returned from the await expressions within the function must all complete, one after the other, before the code in the calling context can move on to the subsequent statements.

OK, now, if your hair is not on fire yet, it is possible to await anything you want:

let d = await Date.now();

That works fine. The value of d will be a Promise, because if the expression that’s awaited isn’t a Promise you effectively get

let d = Promise.resolve().then(_ => Date.now());

Of course d will still be a Promise, and that’s kind-of a mess.

Also, you can call an async function without await and that’s fine, as long as you realize that you’re getting a Promise back.

Because this stuff is really hard to explain in precise mechanical detail, to me it’s better to be in the habit of sticking with async and await and following the rules. Don’t mix .then() code into the mix unless you really need to. It’s easy to forget to return the result of a Promise .then() chain. With async and await, all you have to worry about is keeping track of the functions you’re calling that are either explicitly async or that you know will return Promise objects (because await will work fine in that case too).

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading