Transitioning to TypeScript: The Ultimate Starter Guide - Part 5
Tags: typescript, javascript, programming, webdev
Published: 2023-09-04 12:38:39

## TypeScript from JavaScript Part 5 of 7: Async/Await and Error Handling

Hello again, fellow developers! We have already covered a lot in our journey from JavaScript to TypeScript: basic and advanced types, modules, namespaces, decorators, and type guards. In this part, we will dive into one of the most powerful features of modern JavaScript and TypeScript: async/await and error handling.

As always, remember that the purpose of this series is not just to learn TypeScript, but to understand how it can simplify our work, save time, and elevate our apps. So, let's get started!

## 1. Understanding Promises

Before we dive into async/await, it's important to have a good understanding of Promises, as async/await is built on top of them.

A Promise in JavaScript (and therefore in TypeScript) is an object that represents the eventual completion or failure of an asynchronous operation. It is a way to handle asynchronous operations like HTTP requests, reading files, or timers, and allows us to write non-blocking code.

Here is how you create a Promise:

```typescript
const promise = new Promise((resolve, reject) => {
  const success = true;

  if (success) {
    resolve('The operation was successful.');
  } else {
    reject('The operation failed.');
  }
});

promise.then((message) => {
  console.log('Success:', message);
}).catch((message) => {
  console.log('Failure:', message);
});
```

In this example, we create a Promise that either resolves or rejects based on the value of the `success` variable. If the operation is successful, we call the `resolve` function, otherwise, we call the `reject` function. We can then use the `then` method to handle the resolved value and the `catch` method to handle the rejected value.

## 2. Async/Await

Async/await is a modern way to work with Promises. It makes asynchronous code look and behave a little more like synchronous code, which makes it easier to read and understand.

### a. Async Functions

An async function is a function declared with the `async` keyword. Async functions are instances of the `AsyncFunction` constructor, and the `await` keyword is permitted within them.

```typescript
async function myFunction() {
  return 'Hello, World!';
}

myFunction().then((value) => {
  console.log(value); // Hello, World!
});
```

In this example, `myFunction` is an async function that returns a resolved Promise with the value `'Hello, World!'`. We can then use the `then` method to handle the resolved value.

### b. Await

The `await` keyword is used to pause and resume a JavaScript `AsyncFunction` and to wait for the Promise's resolution or rejection.

```typescript
async function myFunction() {
  const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('Hello, World!');
    }, 2000);
  });

  const result = await promise;
  console.log(result);
}

myFunction();
```

In this example, `myFunction` is an async function that creates a Promise that resolves after 2 seconds. The `await` keyword is used to wait for the Promise to resolve before logging the result to the console.

## 3. Error Handling

Error handling is crucial for any application. In asynchronous code, errors can occur in two ways: synchronous errors (e.g., type errors, syntax errors) and asynchronous errors (e.g., network errors, timeout errors).

### a. Try/Catch

The try/catch statement allows you to define a block of code to be tested for errors while it is being executed (try), and a block of code to be executed if an error occurs (catch).

```typescript
async function myFunction() {
  try {
    const promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        reject('Something went wrong.');
      }, 2000);
    });

    const result = await promise;
    console.log(result);
  } catch (error) {
    console.error(error);
  }
}

myFunction();
```

In this example, `myFunction` is an async function that creates a Promise that rejects after 2 seconds. The `await` keyword is used to wait for the Promise to resolve or reject. If the Promise resolves, the result is logged to the console. If the Promise rejects, the error is caught and logged to the console.

### b. Error Propagation

In asynchronous code, it's important to propagate errors up the call stack so they can be handled properly.

```typescript
async function myFunction() {
  const promise = new Promise((resolve, reject) => {
    setTimeout(() => {
      reject(new Error('Something went wrong.'));
    }, 2000);
  });

  const result = await promise;
  return result;
}

async function main() {
  try {
    const result = await myFunction();
    console.log(result);
  } catch (error) {
    console.error(error.message);
  }
}

main

();
```

In this example, `myFunction` is an async function that creates a Promise that rejects after 2 seconds. The `main` function is another async function that calls `myFunction` and handles any errors that occur.

## Conclusion

In this part, we have learned about async/await and error handling in TypeScript. We have learned how to create async functions, how to use the `await` keyword to wait for Promises to resolve or reject, and how to handle errors using try/catch and error propagation.

Stay tuned for the next part of this series, where we will dive into advanced topics like generics and utility types!

Happy coding! 💻✨