Promises and async functions
Tags: promises, javascript, async
Published: 2021-08-05 21:12:20

---
title: Promises and async functions
published: true
description: Putting async functions inside promises
tags: promises,javascript,async
//cover_image: https://direct_url_to_image.jpg
---

With JavaScript, some operations are asynchronous, and many of these asynchronous operations are signalled via promises.

For instance, fetching data from an API is an asynchronous operation; you need to wait until data from the API has been fully downloaded. So, invoking `fetch` doesn't give you the data. Instead, it gives you a promise, from which you will need to have another function be called to receive said value, as the first parameter of that function.

With a promise, to get the result the instance that is available, you invoke the `then` method, and pass in said function as the first parameter.

Here's an example:

```javascript
const fetchPromise = fetch('http://example.com/some-api/');


fetchPromise.then(response => {
  // Do something with `response` here.
  //
  // Note: the `response` object doesn't actually contain the data. You will
  // need to invoke either `response.text()` to extract the data into a string
  // object, or `response.json()` to extract the data into an object, if the
  // incoming data is valid JSON.
});
```

With `fetch`, we have access to a `response` object.

But from the `response` object, we will need to extract the value. And that is done via invoking either `response.text()`, or `response.json()`. Both of these methods will yield a promise!

So here's what the above code would look like if we wanted to extract the textual value of the response.

```javascript
const fetchPromise = fetch('https://example.com/some-api/');


fetchPromise.then(response => {
  const textPromise = response.text()

  textPromise.then(value => {
    // The paramter `value` will be the extracted string.
  });
});
```

But it gets better.

You know how in arrays, there's a `flatMap` function, and it can accept as return value another array?

The `then` method in promises acts like `flatMap`, where you can return another promise, from the callback function in `then`.

So, to extract the text value, you can invoke the above function like so:

```javascript
const fetchPromise = fetch('https://example.com/some-api/');


fetchPromise.then(response => {
  const textPromise = response.text();

  return textPromise;
});
```

Above, we merely returned the promise. But how do we extract the value?

Before going into that, also note this important fact: the `then` method will always return a promise!

And that promise will—at a high level—be exactly equal to what is returned by the callback in the `then`.

So, to extract the text, the above code would look like so:

```javascript
const fetchPromise = fetch('https://example.com/some-api/');


fetchPromise.then(response => {
  const textPromise = response.text();

  return textPromise;
}).then(text => {
  // The value will be in `text`
});
```

Since we've established where promises typically come from, let's shorten the above code.

```javascript
fetch('https://example.com/some-api/')
  .then(response => response.text())
  .then(text => {
    // The value will be in `text`
  });
```

Let's say the above API yields a string, and we can use that string to invoke another API call. Let's do that.

We can have numerous ways to do that.

We can nest the invocations.

```javascript
fetch('https://example.com/some-api/')
  .then(response => {
    return response.text()
      .then(text => {
        return fetch(`https://example.com/some-api/{text}`)
          .then(response => response.text());
      });
  })
  .then(text => {
    // The value will be in `text`
  });
```

We can nest some of the invocations. Perhaps to group the "response-to-text extraction" logic.

```javascript
fetch('https://example.com/some-api/')
  .then(response => response.text())
  .then(text => {
    return fetch(`https://example.com/some-api/${text}`)
      .then(response => response.text());
  })
  .then(text => {
    // The value will be in `text`
  });
```

Or have everything be sequential.

```javascript
fetch('https://example.com/some-api')
  .then(response => response.text())
  .then(text => {
    return fetch(`https://example.com/some-api/${text}`)
  })
  .then(response => response.text())
  .then(text => {
    // The value will be in `text`
  });
```

## Async functions

OK, the above invocation of `then` is cumbersome, in many situations. So, a solution to limit the number of `then` invocations would be to use an `async` function.

An `async` function looks like this:

```javascript
async function something() {
  return 42;
}
```

An async function doesn't merely return anything. It only returns a promise!

So, invoking `something()` will yield a promise.

```javascript
something()
  .then((value) => {
    console.log(value); // should print 42
  });
```

It gets even better. An async function allows you to resolve promises without invoking `then`. You would use the `await` keyword for that.

So, for instance, if `fetch` were to be invoked inside an async function, it would look like so:

```javascript
async function doSomething() {
  const response = await fetch('https://example.com/some-api');
  return response.text();
}
```

Since async functions return a promise, we can have the above fetch invocations simplified to this:

```javascript
fetch('https://example.com/some-api')
  .then(async response => {
    const text = await response.text();
    const response2 =
      await fetch(`https://example.com/some-api/${text}`);
    return response2.text();
  });
```

I don't know about you, but I'm not a fan of superfluous `response` variables. A solution is to use `then` to avoid creating those variables.


```javascript
fetch('https://example.com/some-api')
  .then(async response => {
    const text = await response.text();
    return fetch(`https://example.com/some-api/${text}`)
      .then(response => response.text());
  });
```