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.
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.