Understanding Promises with JavaScript Visualization

0

Using JavaScript, you frequently encounter the term ‘Promise’. Initially, it might seem complex, but understanding its principles makes handling asynchronous tasks much easier. JavaScript promises are incredibly useful tools for managing asynchronous operations. Let’s take a closer look at how promises work internally.

pixabay

Basic Principles of Promises

Promises are mainly used to create new asynchronous tasks. The basic usage is as follows:

new Promise((resolve, reject) => {
   // Perform asynchronous task
});

A promise written this way will have several important internal states. These states indicate the stage the promise is in. For instance, when the task is completed, the promise’s state changes to `fulfilled`, and the result is `resolved`. Conversely, if the task fails, the state becomes `rejected`, and the result is `rejected`.

Operation of Promises

When a promise is created, the following things happen:

Creation of Promise Object: A promise object is created.

Initialization of Internal States: Several internal slots ([PromiseState], [PromiseResult], [PromiseFulfillReactions], [PromiseRejectReactions]) are initialized.

Start of Asynchronous Task: The asynchronous task begins.

A promise changes its state by calling `resolve` or `reject` when the asynchronous task is completed.

new Promise((resolve, reject) => {
   setTimeout(() => resolve("Done!"), 1000);
}).then(result => console.log(result));

In the above code, `setTimeout` calls `resolve` after 1 second, changing the promise state to `fulfilled`. The `then` handler is then called to print the result.

Chaining Promises

One of the biggest advantages of promises is chaining. You can execute multiple asynchronous tasks sequentially.

new Promise((resolve) => {
   resolve(1);
})
  .then(result => result * 2)
  .then(result => result * 2)
  .then(result => console.log(result));  // Outputs 4

In this example, each `then` handler takes the previous promise’s result and returns a new result. This allows asynchronous tasks to be handled step by step.

Example of Using Promises for Image Processing

For a more practical example, let’s look at loading an image asynchronously and performing subsequent tasks.

function loadImage(src) {
  return new Promise((resolve, reject) => {
    const img = new Image();
    img.onload = () => resolve(img);
    img.onerror = reject;
    img.src = src;
  });
}

loadImage('image.jpg')
 .then(image => {
   console.log('Image loaded');
   return resizeImage(image);  // Imaginary image resizing function
 })
 .then(image => {
   console.log('Image resized');
   return applyGrayscaleFilter(image);  // Imaginary grayscale filter function
 })
 .then(image => {
   console.log('Filter applied');
   return addWatermark(image);  // Imaginary watermark addition function
 })
 .then(image => {
   console.log('All tasks completed');
 });

In this example, the image is loaded asynchronously, and a series of subsequent tasks (resizing, applying a filter, adding a watermark) are performed in sequence. Each task is returned as a promise and executed sequentially through chaining.

Conclusion

Promises are a powerful tool for handling asynchronous tasks in JavaScript. They allow for sequential processing of complex asynchronous operations and make error handling easier. If you want to manage asynchronous tasks efficiently, understanding the concept of promises is essential. Once you grasp the basic concept of promises, you can write asynchronous code that is more readable and maintainable.

References: Lydia Hallie, “Promise Execution”

Leave a Reply