When to mark function as async
Asked Answered
B

4

38

Basically, function must be prefixed with async keyword if await used inside it. But if some function just returns Promise and doesn't awaiting for anything, should I mark the function as async?

Seems like both correct or not?

// with async (returns Promise)
async getActiveQueue() {
   return redisClient.zrangeAsync(activeQueue, 0, -1);
}

// difference? Both could be awaited isn't it?
getActiveQueue() {
   return redisClient.zrangeAsync(activeQueue, 0, -1);
}
Bedwell answered 22/5, 2017 at 7:22 Comment(0)
S
24

if some function just returns Promise and doesn't awaiting for anything, should I mark the function as async?

I would say you shouldn't. The purpose of async/await is to create (and resolve) the promise for you; if you already have a promise to return, then async/await won't give you any benefit for that function.

Both could be awaited isn't it?

await works on promises, not functions. So, await works fine on any promise, regardless of whether that promise is manually created or created behind the scenes by async.

Sneck answered 22/5, 2017 at 13:22 Comment(4)
Using async changes the behaviour of the function for exception handlingProsecution
@Eloims: Indeed! If there is a possibility of a synchronous exception being thrown, I would recommend using async, which would capture the exception and resolve the promise with it.Sneck
Shouldn't it be better for clarity, to mark any function that executes asynchronous operation as async?Collier
@Qwerty: In my code, I prefer a naming convention - an Async suffix.Sneck
P
15

The async keyword is not only about allowing the await keyword in the function. It ensures that your function will always return a Promise, even when exceptions are thrown.

Let's define two identical functions which do not use the await keyword:

async function fnUsingAsync() {
    // Synchronously throw half of the time
    if (Math.random() < .5)
        throw new Error('synchronous error')

    // Return fulfilled/rejected promises half of the time
    return Math.random() < .5 ?
        Promise.resolve('success') :
        Promise.reject(new Error('asynchronous error');
}

function fnNotUsingAsync(x) {
    // Use the exact same body here than function above
}

When calling them, the result is different in case of failure.

// when using the async keyword, the function always returns a promise
// which can be fulfilled or rejected.
// No need for try-catch!
fnUsingAsync()
    .then(result => /* result === 'success' */)
    .catch(error => /* catch both synchronous and asynchronous error */);

// Otherwise, you will need to use a try-catch statement, because
// the exception won't be converted to a rejected promise.
try {
    fnNotUsingAsync()
      .then(result => /* result === 'success' */)
      .catch(error => /* catch asynchronous error only */)
}
catch (error) {
    /* catch synchronous error only */
}
Prosecution answered 20/3, 2018 at 10:20 Comment(0)
A
13

If the function that you call for some unknown reason throws an error, async keyword will make sure that this will be returned as a rejected promise by your function.

async keyword might also be used in functions that would wish to return a promise (e.g. for api consistency) just from the return value, without the need to manually create a Promise object.

Due to the above, I would say that async keyword is not always paired with await.

Amortizement answered 22/5, 2017 at 18:5 Comment(0)
B
0

If your function "doesn't awaiting for anything" - this is usual function, even inside your return function may be async ( this is incapsulation)...

Bridgetbridgetown answered 22/5, 2017 at 12:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.