Maksim Nesterenko
Maksim Nesterenko

Reputation: 6213

When to mark function as async

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);
}

Upvotes: 38

Views: 11340

Answers (4)

Eloims
Eloims

Reputation: 5224

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 */
}

Upvotes: 15

Marinos An
Marinos An

Reputation: 10816

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.

Upvotes: 13

Stephen Cleary
Stephen Cleary

Reputation: 456517

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.

Upvotes: 23

Aleksandr Zolotov
Aleksandr Zolotov

Reputation: 1100

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

Upvotes: 0

Related Questions