Awaiting or just returning asynchronous values in JavaScript async/await functions
Tags: node, javascript
Published: 2019-10-03 19:07:31

---
title: Awaiting or just returning asynchronous values in JavaScript async/await functions
published: true
canonical_url: https://www.coreycleary.me/awaiting-or-just-returning-asynchronous-values-in-javascript-async-await-functions/
tags: node,javascript
---

<em><strong>Originally published at <a href="https://www.coreycleary.me/awaiting-or-just-returning-asynchronous-values-in-javascript-async-await-functions/">coreycleary.me</a></strong>. This is a cross-post from my content blog. I publish new content every week or two, and you can <a href="https://www.coreycleary.me/about/">sign up to my newsletter</a> if you'd like to receive my articles directly to your inbox! I also regularly send cheatsheets and other freebies.</em>

When you're writing asynchronous code in JavaScript using `async/await` functions, it can be confusing to know how to handle returning an asynchronous value. Do you need to `await` the promise before you return? Or should you just return the promise?

Let's look at some examples:

```javascript
async function getAvailableItems(items) {
  const formattedItems = items.filter(item => !item.name)
  
  try {
    // checks in database
    return await checkIfItemsAreAvailable(formattedItems)
  } catch(e) {
    console.error(e)
  }
}
```

How is that different than this?

```javascript
async function getAvailableItems(items) {
  const formattedItems = items.filter(item => !item.name)
  
  // checks in database
  return checkIfItemsAreAvailable(formattedItems)
}
```

So in the first example, we add a try/catch to catch the rejected promise. Imagine the database is down, so when we make the `checkIfItemsAreAvailable` call, it results in a rejected promise. In the first example, we've caught it!

But in the second example, we haven't. If the `checkIfItemsAreAvailable` does NOT fail, then it doesn't matter.

Why? Well, when we call `getAvailableItems`, because it is an `async` function and `async` functions return promises anyways, if you `await` the call to `checkIfItemsAreAvailable` you just add a bit of extra time waiting for it to resolve before you return it.

Let's look at the <a href="https://eslint.org/docs/rules/no-return-await" rel="noopener" target="_blank">ESLint rule for this</a>:

<blockquote>Since the return value of an async function is always wrapped in Promise.resolve, return await doesn’t actually do anything except add extra time before the overarching Promise resolves or rejects. The only valid exception is if return await is used in a try/catch statement to catch errors from another Promise-based function.</blockquote>

<h3>So, how to decide?</h3>
The question then becomes, are you OK with not catching the rejected promise (i.e. - not using a try/catch) from within the async function?

This can be a tough question mostly because it tends to be application-specific and depends on how your code is currently structured.

Because rejections bubble/propagate, as long as you have a function higher up that catches the rejection, you're probably OK not catching the rejection in the `getAvailableItems` function.

For example, it's a pattern in Express to catch things at the "root", at the route level, like so:

```javascript
function wrapAsync(fn) {
  return function(req, res, next) {
    // Make sure to `.catch()` any errors and pass them along to the `next()`
    // middleware in the chain, in this case the error handler.
    fn(req, res, next).catch(next);
  };
}

router.post('/search', wrapAsync(itemController.getAvailableItems))
```

The route is the "root" level because it is the first bit of code the request will hit (after middleware like authentication, etc). So any rejected promises that happen after that will be caught.

If we just return the promise like so:
```javascript
async function getAvailableItems(items) {
  const formattedItems = items.filter(item => !item.name)
  
  // checks in database
  return checkIfItemsAreAvailable(formattedItems)
}
```

...and it fails, the `wrapAsync` function at the route level will catch it.

However, you might not have a "root" handler like this in place depending on what kind of application you're working on. So you need to take that into consideration.

<h3>Summary</h3>
My general rule is if I'm able to try/catch the promise elsewhere, then I'll probably skip the try/catch and just return the promise without awaiting:
```javascript
async function getAvailableItems(items) {
  const formattedItems = items.filter(item => !item.name)
  
  // return promise, don't await
  return checkIfItemsAreAvailable(formattedItems)
}
```

If not, for example, if there are multiple kinds of rejections that can be thrown, I'll use a try/catch.

It takes a bit of practice recognizing the scenarios but the above can serve as a useful guideline to get started.

Love JavaScript but still getting tripped up by asynchronous code? I publish articles on JavaScript and Node every 1-2 weeks, so if you want to receive all new articles directly to your inbox, <a href="https://www.coreycleary.me/about/">here's that link again</a> to subscribe to my newsletter!