Async/await in TypeScript
Tags: javascript, typescript
Published: 2020-03-02 14:00:35

---
title: Async/await in TypeScript
published: true
date: 2020-02-27 14:00:43 UTC
tags: javascript,typescript
canonical_url: https://blog.logrocket.com/async-await-in-typescript/
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/9gb4s01jkc8auohxhol0.png
---
**Written by [Olasunkanmi John Ajiboye](https://blog.logrocket.com/author/olasunkanmiajiboye/)**✏️

If you’re reading this blog, you probably have some familiarity with asynchronous programming in JavaScript, and you may be wondering how it works in TypeScript.

Since TypeScript is a superset of JavaScript, async/await works the same, but with some extra goodies and type safety. TypeScript enables you to type-safe the expected result and even type-check errors, which helps you detect bugs earlier on in the development process.

async/await is essentially a [syntactic sugar](https://medium.com/@matt.mcalister93/async-and-await-syntactic-sugar-for-promises-in-javascript-aee7ace36d14) for promises, which is to say the `async/await` keyword is a wrapper over promises. An `async` function always returns a promise. Even if you omit the `Promise` keyword, the compiler will wrap your function in an immediately resolved promise.

Allow me to demonstrate:

```jsx
const myAsynFunction = async (url: string): Promise<T> => {
    const { data } = await fetch(url)
    return data
}

const immediatelyResolvedPromise = (url: string) => {
    const resultPromise = new Promise((resolve, reject) => {
        resolve(fetch(url))
    })
    return  resultPromise
}
```

Although they look totally different, the code snippets above are more or less equivalent. [Async/await](https://blog.logrocket.com/promise-chaining-is-dead-long-live-async-await-445897870abc/) simply enables you to write the code in a more synchronous manner and unwraps the promise in-line for you. This is powerful when you’re dealing with complex asynchronous patterns.

To get the most out of the `async/await` syntax, you’ll need a basic understanding of promises. Let’s take a closer look at Promises on a fundamental level.

[![LogRocket Free Trial Banner](https://i0.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/f760c-1gpjapknnuyhu8esa3z0jga.png?resize=1200%2C280&ssl=1)](https://logrocket.com/signup/)

## What is a promise in TypeScript?

According to [Lexico](https://www.lexico.com/en/definition/promise), a promise, in the English language, is “a declaration or assurance that one will do a particular thing or that a particular thing will happen.” In JavaScript, a promise refers to the expectation that something will happen at a particular time, and your app relies on the result of that future event to perform certain other tasks.

To show what I mean, I’ll break down a real-world example and commute it into pseudocode and then actual TypeScript code.

Let’s say I have a lawn to mow. I contact a mowing company that promises to mow my lawn in a couple of hours. I, in turn, promise to pay them immediately afterward, provided the lawn is properly mowed.

Can you spot the pattern? The first obvious thing to note is that the second event relies entirely on the previous one. If the first event’s promise is fulfilled, the next event’s will execute. The promise in that event is then either fulfilled or rejected or remains pending.

Let’s look at this sequence step by step and then code it out.

![Diagram Showing a Promise Sequence in TypeScript](https://i1.wp.com/blog.logrocket.com/wp-content/uploads/2020/02/promise-typescript.png?resize=502%2C654&ssl=1)

## The promise syntax

Before we write out the full code, it makes sense to examine the syntax for a promise — specifically, an example of a promise that resolves into a string.

We declared a `promise` with the `new + Promise` keyword, which takes in the `resolve` and `reject` arguments. Now let’s write a promise for the flow chart above.

```jsx
// I send a request to the company. This is synchronous
// company replies with a promise
const angelMowersPromise = new Promise<string>((resolve, reject) => {
    // a resolved promise after certain hours
    setTimeout(() => {
        resolve('We finished mowing the lawn')
    }, 100000) // resolves after 100,000ms
    reject("We couldn't mow the lawn")
})

const myPaymentPromise = new Promise<Record<string, number | string>>((resolve, reject) => {
    // a resolved promise with  an object of 1000 Euro payment
    // and a thank you message
    setTimeout(() => {
        resolve({
            amount: 1000,
            note: 'Thank You',
        })
    }, 100000)
    // reject with 0 Euro and an unstatisfatory note
    reject({
        amount: 0,
        note: 'Sorry Lawn was not properly Mowed',
    })
})
```

In the code above, we declared both the company’s promises and our promises. The company promise is either resolved after 100,000ms or rejected. A `Promise` is always in one of three states: `resolved` if there is no error, `rejected` if an error is encountered, or `pending` if the `promise` has been neither rejected nor fulfilled. In our case, it falls within the `100000ms` period.

But how can we execute the task in a sequential and synchronous manner? That’s where the `then` keyword comes in. Without it, the functions simply run in the order in which they resolve.

## Sequential execution with `.then`

Now we can chain the promises, which allows them to run in sequence with `.then`. This functions like a normal human language — do this and then that and then that, and so on.

```jsx
angelMowersPromise
    .then(() => myPaymentPromise.then(res => console.log(res)))
    .catch(error => console.log(error))
```

The code above will run the `angelMowersPromise`. If there is no error, it’ll run the `myPaymentPromise`. If there is an error in either of the two promises, it’ll be caught in the `catch` block.

Now let’s look at a more technical example. A common task in frontend programming is to make network requests and respond to the results accordingly.

Below is a request to fetch a list of employees from a remote server.

```jsx
const api =  'http://dummy.restapiexample.com/api/v1/employees'
   fetch(api)
    .then(response => response.json())
    .then(employees => employees.forEach(employee => console.log(employee.id)) // logs all employee id
    .catch(error => console.log(error.message))) // logs any error from the promise
```

There may be times when you need numerous promises to execute in parallel or in sequence. Constructs such as `Promise.all` or `Promise.race` are especially helpful in these scenarios.

Imagine, for example, that you need to fetch a list of 1,000 GitHub users, then make an additional request with the ID to fetch avatars for each of them. You don’t necessarily want to wait for each user in the sequence; you just need all the fetched avatars. We’ll examine this in more detail later when we discuss `Promise.all`.

Now that you have a fundamental grasp of promises, let’s look at the `async/await` syntax.

## `async/await`

Async/await is a surprisingly easy syntax to work with promises. It provides an easy interface to read and write promises in a way that makes them appear synchronous.

An `async/await` will always return a `Promise`. Even if you omit the `Promise` keyword, the compiler will wrap the function in an immediately resolved `Promise`. This enables you to treat the return value of an [`async` function](https://blog.logrocket.com/the-visual-learners-guide-to-async-js-62a0a03d1d57/) as a `Promise`, which is quite useful when you need to resolve numerous asynchronous functions.

As the name implies, `async` always goes hand in hand with `await`. That is, you can only `await` inside an `async` function. The `async` function informs the compiler that this is an asynchronous function.

If we convert the promises from above, the syntax looks like this:

```jsx
const myAsync = async (): Promise<Record<string, number | string>> => {
    await angelMowersPromise
    const response = await myPaymentPromise
    return response
}
```

As you can see immediately, this looks more readable and appears synchronous. We told the compiler on line 3 to await the execution of `angelMowersPromise` before doing anything else. Then, we return the response from the `myPaymentPromise`.

You may have noticed that we omitted error handling. We could do this with the `catch` block after the `.then` in a promise. But what happens if we encounter an error? That leads us to `try/catch`.

## Error handling with `try/catch`

We’ll refer to the employee fetching example to the error handling in action, since it is likely to encounter an error over a network request.

Let’s say, for instance, that the server is down, or perhaps we sent a malformed request. We need to pause execution to prevent our program from crashing. The syntax will look like this:

```jsx
interface Employee {
    id: number
    employee_name: string
    employee_salary: number
    employee_age: number
    profile_image: string
}
const fetchEmployees = async (): Promise<Array<Employee> | string> => {
    const api = 'http://dummy.restapiexample.com/api/v1/employees'
    try {
        const response = await fetch(api)
        const { data } = await response.json()
        return data
    } catch (error) {
        if (error) {
            return error.message
        }
    }
}
```

We initiated the function as an `async` function. We expect the return value to be of the `typeof` array of employees or a string of error messages. Therefore, the type of Promise is `Promise<Array<Employee> | string>`.

Inside the `try` block are the expressions we expect the function to run if there are no errors. The `catch` block captures any error that arises. In that case, we’d just return the `message` property of the `error` object.

The beauty of this is that any error that first occurs within the `try` block is thrown and caught in the `catch` block. An uncaught exception can lead to hard-to-debug code or even break the entire program.

## Concurrent execution with `Promise.all`

As I stated earlier, there are times when we need promises to execute in parallel.

Let’s look at an example from our employee API. Say we first need to fetch all employees, then fetch their names, then generate an email from the names. Obviously, we’ll need to execute the functions in a synchronous manner and also in parallel so that one doesn’t block the other.

In this case, we would make use of `Promise.all`. According to Mozilla, “`Promise.all` is typically used after having started multiple asynchronous tasks to run concurrently and having created promises for their results so that one can wait for all the tasks being finished.”

In pseudocode, we’d have something like this:

- Fetch all users => `/employee`
- Wait for all user data. Extract the `id` from each user. Fetch each user => `/employee/{id}`
- Generate email for each user from their username

```jsx
const baseApi = 'https://reqres.in/api/users?page=1'
const userApi = 'https://reqres.in/api/user'

const fetchAllEmployees = async (url: string): Promise<Employee[]> => {
    const response = await fetch(url)
    const { data } = await response.json()
    return data
}

const fetchEmployee = async (url: string, id: number): Promise<Record<string, string>> => {
    const response = await fetch(`${url}/${id}`)
    const { data } = await response.json()
    return data
}
const generateEmail = (name: string): string => {
    return `${name.split(' ').join('.')}@company.com`
}

const runAsyncFunctions = async () => {
    try {
        const employees = await fetchAllEmployees(baseApi)
        Promise.all(
            employees.map(async user => {
                const userName = await fetchEmployee(userApi, user.id)
                const emails = generateEmail(userName.name)
                return emails
            })
        )
    } catch (error) {
        console.log(error)
    }
}
runAsyncFunctions()
```

In the above code, `fetchEmployees` fetches all the employees from the `baseApi`. We `await` the response, convert it to `JSON`, then return the converted data.

The most important concept to keep in mind is how we sequentially executed the code line by line inside the `async` function with the `await` keyword. We’d get an error if we tried to convert data to JSON that has not been fully awaited. The same concept is applicable to `fetchEmployee`, except that we’d only fetch a single employee. The more interesting portion is the `runAsyncFunctions`, where we run all the async functions concurrently.

First, wrap all the methods within `runAsyncFunctions` inside a `try/catch` block. Next, `await` the result of fetching all the employees. We need the `id` of each employee to fetch their respective data, but what we ultimately need is information about the employees.

This is where we can call upon `Promise.all` to handle all the `Promises` concurrently. Each `fetchEmployee` `Promise` is executed concurrently for all the employees. The awaited data from the employees’ information is then used to generate an email for each employee with the `generateEmail` function.

In the case of an error, it propagates as usual, from the failed promise to `Promise.all`, and then becomes an exception we can catch inside the `catch` block.

## Key takeaways

`async` and `await` enable us to write asynchronous code in a way that looks and behaves like synchronous code. This makes the code much easier to read, write, and reason about.

I’ll close with some key concepts to keep in mind as you’re working on your next asynchronous project in TypeScript.

- `await` only works inside an `async` function
- The function marked with the `async` keyword always returns a `Promise`
- If the return value inside `async` doesn’t return a `Promise`, it will be wrapped in an immediately resolved `Promise`
- Execution is paused when an `await` keyword is encountered until a `Promise` is completed
- `await` will either return a result from a fulfilled `Promise` or throw an exception from a rejected `Promise`

* * * 
## Plug: [LogRocket](https://logrocket.com/signup/), a DVR for web apps
 
![LogRocket Dashboard Free Trial Banner](https://i2.wp.com/blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png?resize=1200%2C677&ssl=1)
 
[LogRocket](https://logrocket.com/signup/) is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.
 
In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.
 
[Try it for free](https://logrocket.com/signup/).
* * *

The post [Async/await in TypeScript](https://blog.logrocket.com/async-await-in-typescript/) appeared first on [LogRocket Blog](https://blog.logrocket.com).