SEUNGJUN LEE.

JavaScript Promises: Asynchronous Processing and Conceptualization

Promise

JavaScript originally used the callback pattern for asynchronous processing. However, this approach led to poor code readability due to “callback hell,” and it was challenging to handle errors and manage multiple tasks. To address these issues, ES6 introduced Promises.

In JavaScript, asynchronous tasks include Timers (setTimeout/setInterval), HTTP requests, and DOM event handling. These tasks are executed separately from the main thread, allowing parallel processing without blocking the flow of other operations.

Initially, callback functions were used to control the order of asynchronous tasks. However, this led to the issue of callback hell, where nested callbacks made the code increasingly complex.

Creating a Promise

  • A Promise is instantiated using the Promise constructor.

  • The constructor takes a callback function with resolve and reject as parameters.

  • A Promise has the following states:

    • pending: The initial state, when the task is not yet completed.

    • fulfilled: The state when the task is successfully completed (resolve is called).

    • rejected: The state when the task fails (reject is called).

    • settled: The state when the task is completed (either fulfilled or rejected).

Asynchronous functions implemented with Promises must return a Promise object.

Subsequent tasks can be chained using the object’s methods (then, catch).

Promise Chaining

Promise chaining resolves the problem of callback hell.

  • The first then executes with the value passed from resolve.

  • Each then can return a value, which is passed to the next then.

  • Chaining allows sequential processing of asynchronous tasks.

  • If an error occurs, the chain is interrupted, and the execution moves to catch for error handling.

// Creating a Promise
const fetchData = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const success = true;
      if (success) {
        resolve('Data has been retrieved!'); // Call resolve on success
      } else {
        reject('Error occurred!'); // Call reject on failure
      }
    }, 1000); // Execute after 1 second
  });
};
// Promise chaining
fetchData()
  .then((result) => {
    console.log(result); // 'Data has been retrieved!'
    return 'Proceeding to the next task';
  })
  .then((nextStep) => {
    console.log(nextStep); // 'Proceeding to the next task'
  })
  .catch((error) => {
    console.error(error); // Executes if an error occurs
  });

Methods

Promises have four built-in methods: resolve, reject, all, and race.

Among them, Promise.all:

  • Executes multiple Promises in parallel and returns an array of results when all Promises are successfully fulfilled.

  • If even one Promise fails (is rejected), it immediately returns the rejection, halting further processing.

Keywords (Topics or terms to study further)

  • Asynchronous

  • Callback

  • Event Loop

Reference:

6.9 Promise