Promise Class from Scratch

Implementation of the Promise class in JavaScript.

In this note, we will implement the Promise class from scratch.
This walkthrough explains the internal working of JavaScript promises.

Let's start with the core idea.


What is a Promise?

Forget the technical definition for a moment.
Let's understand it with a simple example.

When you order food from platforms like Zomato or Swiggy, after completing the payment process you receive an order summary that says:

Arriving in 20 min

At that moment:

  1. You don’t have the food yet
  2. You only have a confirmation that it will arrive in the future

That confirmation behaves like a Promise.

You are free to do other things like:

  • Watching movies
  • Playing games
  • Doing other work

You are not blocked waiting at the door.

Later one of two things happens:

  • Food arrives → Success
  • Order gets cancelled → Failure

How This Relates to JavaScript

Similarly in JavaScript:

When you make an API call, JavaScript immediately returns a Promise object.

Initially, the promise state is:

PENDING

After the async task finishes:

  • Success → Promise becomes
    fulfilled
  • Failure → Promise becomes
    rejected

So a Promise represents a value that will be available in the future.


Implementing Our Own Promise

Now let's build a simplified Promise implementation.

We will call it:

MyPromise

Step 1: Promise States

A promise can exist in three states:

const promiseState = { PENDING: "pending", FULFILLED: "fulfilled", REJECTED: "rejected", };

Step 2: Promise Class Implementation

const promiseState = { PENDING: "pending", FULFILLED: "fulfilled", REJECTED: "rejected", }; class MyPromise { #thenCallbackFunArr = []; #catchCallbackFunArr = []; #finallyCallbackFunArr = []; #state = promiseState.PENDING; #sucessValue = undefined; #errorValue = undefined; constructor(executerFun) { this.executerFun = executerFun; this.executerFun(this.#resolver.bind(this), this.#rejecter.bind(this)); } #resolver(value) { if (this.#state === promiseState.FULFILLED) return; this.#sucessValue = value; this.#state = promiseState.FULFILLED; // run all then callbacks this.#thenCallbackFunArr.forEach((cb) => cb(value)); // run finally callbacks this.#finallyCallbackFunArr.forEach((cb) => cb()); } #rejecter(error) { if (this.#state === promiseState.REJECTED) return; this.#errorValue = error; this.#state = promiseState.REJECTED; // run catch callbacks this.#catchCallbackFunArr.forEach((cb) => cb(error)); // run finally callbacks this.#finallyCallbackFunArr.forEach((cb) => cb()); } then(cb) { if (this.#state === promiseState.FULFILLED) { cb(this.#sucessValue); } else { this.#thenCallbackFunArr.push(cb); } return this; } catch(cb) { if (this.#state === promiseState.REJECTED) { cb(this.#errorValue); } else { this.#catchCallbackFunArr.push(cb); } return this; } finally(cb) { if (this.#state !== promiseState.PENDING) { cb(); } else { this.#finallyCallbackFunArr.push(cb); } return this; } } module.exports = MyPromise;

What Is Still Missing

This is a simplified Promise implementation.

Real JavaScript promises support many more features such as:

  • Promise chaining
  • Microtask queue
  • Error propagation
  • Promise.all
  • Promise.race
  • Promise.any
  • Promise.allSettled

We will implement these in future notes.

Design & Developed by Amit
© 2026. All rights reserved.