A Simple Implementation of Promises in JavaScript: Meet the Vow Class
Tags: javascript, asynchronousprogramming, promises, vowclass
Published: 2023-07-05 18:47:02

Asynchronous programming is an essential aspect of modern web development, and JavaScript provides several mechanisms to handle it. One of the most popular ones is the Promise object, which simplifies and standardizes the way we deal with asynchronous operations.

In essence, a promise is an object that represents the eventual completion (or failure) of an asynchronous operation and provides a way to handle its result or error. The operation can be anything that takes time to complete, such as fetching data from a server, reading a file from disk, or waiting for user input.

Promises work by following a well-defined lifecycle that consists of three states: pending, fulfilled, and rejected. A promise starts in the pending state, which means that the operation is still ongoing, and no result or error is available yet. Once the operation completes successfully, the promise transitions to the fulfilled state, and its value becomes available. On the other hand, if the operation fails, the promise transitions to the rejected state, and its reason (i.e., the error object) becomes available.

To handle the result or error of a promise, we can attach callbacks to it using the `then()` and `catch()` methods. The `then()` method takes two optional arguments: a resolve callback, which is called if the promise is fulfilled, and a reject callback, which is called if the promise is rejected. The `catch()` method is a shorthand for `then(undefined, rejectCallback)` and is called only if the promise is rejected.

Moreover, we can chain promises by returning a new promise from a resolve or reject callback in a `then()` method. This allows us to transform or filter the result of a promise or to sequence multiple asynchronous operations.

Now that we have a basic understanding of how promises work, let's dive into the code. I have implemented a Promise-like object called `Vow` that follows the same principles as the native Promise object in JavaScript.

The `Vow` class defines a private state property (`#state`) that starts in the pending state, and two private value properties (`#value` and `#reason`) that hold the result or error of the promise. It also defines two private callback properties (`#onSuccess` and `#onFail`) that are bound to the instance of the class and are used to handle the completion of the asynchronous operation.

The `Vow` class also defines a private callbacks property (`#callbacks`) that holds an array of callback functions that are registered to be called when the promise is fulfilled or rejected. The `#processQueue()` method checks the state of the promise and calls the registered callbacks with the current value or reason if the promise is settled.

The `Vow` class implements the `then()`, `catch()`, and `finally()` methods to attach callbacks to the promise and return a new promise that reflects the result or error of the original promise. The `then()` method registers the resolve and reject callbacks to the callbacks array and returns a new promise that resolves or rejects with the return value of the callbacks. The `catch()` method registers a reject callback that throws the reason of the original promise, and the `finally()` method registers a callback that is called regardless of whether the original promise is fulfilled or rejected.

Finally, the `Vow` class defines several static methods that provide utility functions to work with arrays of promises, such as `all()`, `allSettled()`, `race()`, and `any()`. These methods use the `Vow` class to create and manage promises that reflect the result of the input promises.

Great! So, to sum it up: the `Vow` class is a simplified implementation of the Promise object in JavaScript that can help you understand how promises work and how to handle asynchronous operations in a standard way. If you're interested in trying it out, you can access the code on [GitHub repository](https://github.com/waelhabbal/js-promise-implementation), I hope you find this implementation and the explanations useful.