What is Promises in JavaScript

·

5 min read

Cover Image for What is Promises in JavaScript

Promises are a way of handling asynchronous operations in JavaScript. They are used to make asynchronous code more manageable and easier to read. A Promise is an object that represents the eventual completion (or failure) of an asynchronous operation and its resulting value.

A Promise can be in one of three states:

  • Pending: The Promise has been created, but the promise is neither fulfilled nor rejected.

  • Fulfilled: The asynchronous operation has been completed successfully, and the Promise has a value.

  • Rejected: The asynchronous operation has failed, and the Promise has a reason for the failure.

How to Work With Promises

To use a Promise, you first create it using the new Promise() constructor. The constructor takes a single argument, which is a function called the executor. The executor is called immediately when the Promise is created, and it is responsible for starting the asynchronous operation.

Once the asynchronous operation is complete, the executor calls one of the following two functions:

  • resolve(value): This function is called if the asynchronous operation is successful. The value parameter is the value that the Promise will be fulfilled with.

  • reject(reason): This function is called if the asynchronous operation fails. The reason parameter is the reason for the failure.

💡
Once the Promise has been fulfilled or rejected, it cannot change its state.

To handle the outcome of a Promise, you use the then() and catch() methods. The then() method is called when the Promise is fulfilled, and the catch() method is called when the Promise is rejected.

fetch('https://jsonplaceholder.typicode.com/todos/1')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error));

This code will fetch a JSON object from the URL https://jsonplaceholder.typicode.com/todos/1. If the fetch is successful, the code will then parse the JSON object and log it to the console. If the fetch fails, the code will log the error to the console.

Benefits of using Promises

Promises are a powerful tool for handling asynchronous operations in JavaScript. They make asynchronous code more manageable and easier to read, and they can help to prevent callback hell.

Here are some of the benefits of using Promises:

  • Improved readability: Promises can make asynchronous code more readable by making it clear which code is responsible for starting the asynchronous operation and which code is responsible for handling the result.

  • Reduced callback hell: Promises can help to prevent callback hell by allowing you to chain together multiple asynchronous operations without having to nest callbacks.

  • Error handling: Promises provide a standard way of handling errors in asynchronous operations.

How Promises Are Different from Callbacks

Callbacks and Promises are both mechanisms for handling asynchronous operations in JavaScript. However, they differ in their approach and syntax.

  • Callbacks - Callbacks are functions passed as arguments to other functions to be executed later. This approach can lead to callback hell, where nested callbacks become difficult to manage and error handling becomes convoluted.

  • Promises - Promises are objects that represent the eventual completion or failure of an asynchronous operation. They provide a more structured and organized way to handle asynchronous code.

Callbacks

  1. Callback Hell (Callback Pyramids): When multiple asynchronous operations are nested, it can lead to callback hell, where the code becomes deeply nested and hard to read or maintain.
asyncOperation1((result1) => {
  asyncOperation2(result1, (result2) => {
    asyncOperation3(result2, (result3) => {
      // More nested callbacks...
    });
  });
});
  1. Error Handling: Error handling in callbacks can become complex, as each callback needs to handle its own errors.
asyncOperation((result) => {
  anotherAsyncOperation(result, (anotherResult) => {
    // Handle anotherResult
  }, (error) => {
    // Handle error from anotherAsyncOperation
  });
}, (error) => {
  // Handle error from asyncOperation
});

Promises

  1. Chaining: Promises allow for a more linear and readable flow of code by enabling method chaining with .then() and .catch().
asyncOperation1()
  .then(result1 => asyncOperation2(result1))
  .then(result2 => asyncOperation3(result2))
  .then(result3 => {
    // Handle final result
  })
  .catch(error => {
    // Handle errors from any step
  });
  1. Error Handling: Errors can be handled at a single point in the chain using the .catch() method, making error management more centralized and easier to follow.
asyncOperation1()
  .then(result1 => asyncOperation2(result1))
  .then(result2 => asyncOperation3(result2))
  .then(result3 => {
    // Handle final result
  })
  .catch(error => {
    // Handle errors from any step
  });
  1. Readability: Promises offer a more readable and maintainable code structure, especially for complex asynchronous scenarios.
asyncOperation1()
  .then(result1 => asyncOperation2(result1))
  .then(result2 => asyncOperation3(result2))
  .then(result3 => finalOperation(result3))
  .catch(error => handleError(error));
  1. Built-in Error Propagation: Promises automatically propagate errors to the nearest .catch() block in the chain, simplifying error handling.

Here's a table summarizing the key differences between callbacks and Promises:

FeatureCallbacksPromises
SyntaxPassing functions as argumentsUsing then() and catch() methods
Handling of multiple asynchronous operationsCan lead to callback hellChaining promises together
Error handlingRequires explicit error handlingBuilt-in error handling
ReadabilityCan be less readable, especially when nestedGenerally more readable and organized

In summary, Promises offer several advantages over callbacks, making them a more preferred choice for handling asynchronous operations in JavaScript:

  • Improved readability: Promises provide a clear and structured way to represent and handle asynchronous operations, making the code more readable and easier to follow.

  • Reduced callback hell: Promises prevent the nesting of callbacks, which can become messy and difficult to manage. Instead, Promises allow you to chain together multiple asynchronous operations, making the code more organized and maintainable.

  • Standardized error handling: Promises have a built-in mechanism for handling errors, making error handling more consistent and straightforward.

While callbacks were once the primary method for handling asynchronous operations in JavaScript, Promises have become the preferred approach, especially for larger and more complex projects. They offer a more organized, readable, and maintainable way to manage asynchronous code, reducing the risk of callback hell and improving overall code quality.

Sounds too complicated? Read the Simplified Versions

Read more about React & JavaScript

Follow me for more such content