Promises in JavaScript and TypeScript - Simple & Code Example

What are Promises?

Promises are a way of handling asynchronous code in JavaScript. They provide a way to represent the eventual completion (or failure) of an asynchronous operation and allow us to write code that is easier to read and reason about.

At their core, promises are simply objects that represent a value that is not yet available. They have three states: pending, fulfilled and rejected. When a promise is in the pending state, it means that the value it represents is not yet available. When a promise is fulfilled, it means that the value it represents is available and the promise has been resolved successfully. When a promise is rejected, it means that an error has occurred and the promise has been rejected.

What Are Promises Used For?

Promises are commonly used for handling asynchronous operations in JavaScript, such as making HTTP requests, working with timers, and reading/writing files. They provide a way to write code that is more readable and maintainable by avoiding deeply nested callbacks (known as "callback hell") and allowing us to chain asynchronous operations together.

Using Promises in JavaScript

To use promises in JavaScript, we create a new promise using the Promise constructor. The constructor takes a function as its argument, which in turn takes two arguments: resolve and reject. These functions are used to resolve or reject the promise with a value.

Here's an example of using a promise to simulate an asynchronous operation that resolves after a certain amount of time:

function wait(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

wait(1000)
  .then(() => {
    console.log('Done!');
  })
  .catch((error) => {
    console.error(error);
  });

In this example, we define a wait function that returns a new promise that resolves after a certain number of milliseconds. We then call the wait function with an argument of 1000 (i.e. one second) and use the then method to log a message to the console when the promise is fulfilled.

We also use the catch method to handle any errors that may occur during the operation.

in TypeScript:

function wait(ms: number): Promise<void> {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

wait(1000)
  .then(() => {
    console.log('Done!');
  })
  .catch((error) => {
    console.error(error);
  });

Using Promises for HTTP Requests

One of the most common uses of promises in JavaScript is for making HTTP requests. When we make an HTTP request using JavaScript, the server responds with a promise that represents the response. We can then use the then method to handle the response and the catch method to handle any errors that may occur.

Here's an example of using the fetch function to make an HTTP request and receive a promise in return:

fetch('https://api.example.com/data')
  .then((response) => {
    return response.json();
  })
  .then((data) => {
    console.log(data);
    // Do something with the data here
  })
  .catch((error) => {
    console.error(error);
  });

In this example, we call the fetch function with a URL and receive a promise in return. We then use the first then method to parse the response as JSON and return it. We use the second then method to log the data to the console and do something with it.

in TypeScript:

function fetchUsers(): Promise<User[]> {
  return fetch('https://jsonplaceholder.typicode.com/users')
    .then(response => response.json())
    .then(data => data as User[])
    .catch(error => {
      console.error(error);
      throw error;
    });
}

interface User {
  id: number;
  name: string;
  email: string;
}

fetchUsers()
  .then(users => console.log(users))
  .catch(error => console.error(error));

In this example, we define a function called fetchUsers that makes an HTTP GET request to the specified URL and returns a promise that resolves with an array of User objects. We use the then method to parse the response data as JSON and cast it to an array of User objects. We also use the catch method to handle any errors that may occur during the request.

We then call the fetchUsers function and chain a then method to log the array of User objects to the console. Finally, we use the catch method to handle any errors that may occur during the request.

Promises provide a way to work with asynchronous code in a more intuitive and maintainable way. They allow us to write code that is more readable and easier to reason about, by avoiding the need for deeply nested callback functions. Additionally, promises provide a consistent interface for handling errors that may occur during asynchronous operations.

One benefit of receiving a promise from the HTTP response is that it allows us to use the then method to handle the response in a more readable and maintainable way. By using promises for HTTP requests, we can write more concise and expressive code that is easier to understand and debug. This can lead to more efficient development and better-quality code overall.

0
Subscribe to my newsletter

Read articles from {{ MonaCodeLisa }} directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

{{ MonaCodeLisa }}
{{ MonaCodeLisa }}

Hello, I'm Esther White, I am an experienced FullStack Web Developer with a focus on Angular & NodeJS.