JavaScript Promise Simple Implementation

huabin zhanghuabin zhang
3 min read

Key Concepts of Promise

  1. Three States:
  • pending (in progress)

  • fulfilled (successfully completed)

  • rejected (failed)

  1. Irreversible State Transition: Once a promise changes from pending to fulfilled or rejected, it cannot change again.

  2. The then Method:

    • Takes two arguments: a success callback (onFulfilled) and a failure callback (onRejected)

    • Supports chaining via then

Simple Implementation

According to the key concepts of Promise, we need to implement the following features:

  • Promise has three states: pending, fulfilled, and rejected

  • Promise can be resolved or rejected, and the status can only be changed from pending to fulfilled or rejected

  • Promise can have multiple then methods, and they can be chained together

class MyPromise {
  constructor(executor) {
    // init Data
    this.status = "pending";
    this.value = undefined;
    this.reason = undefined;

    // sava async callbacks
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];

    // resolve method
    const resolve = (value) => {
      if (this.status === "pending") {
        this.status = "fulfilled";
        this.value = value;
        // status changed, execute all the callbacks in the array
        this.onFulfilledCallbacks.forEach((fn) => fn());
      }
    };

    // reject method
    const reject = (reason) => {
      if (this.status === "pending") {
        this.status = "rejected";
        this.reason = reason;
        this.onRejectedCallbacks.forEach((fn) => fn());
      }
    };

    try {
      // execute the executor function, and pass resolve and reject method to it
      executor(resolve, reject);
    } catch (err) {
      reject(err);
    }
  }

  then(onFulfilledCallback, onRejectedCallback) {
    return new MyPromise((resolve, reject) => {
      if (this.status === "fulfilled") {
        const result = onFulfilledCallback(this.value);
        resolve(result);
      } else if (this.status === "rejected") {
        const reslut = onRejectedCallback(this.reason);
        resolve(result);
      } else {
        // pending status, put into callback arrays
        this.onFulfilledCallbacks.push(() => {
          const result = onFulfilledCallback(this.value);
          resolve(result);
        });

        this.onRejectedCallbacks.push(() => {
          const reslut = onRejectedCallback(this.reason);
          resolve(result);
        });
      }
    });
  }
}

This is a simple implementation of Promise in JavaScript. It supports the basic functionality of Promise, including the then method and the resolve / reject methods.

It does not support all the features of the native Promise, but it is a good starting point for understanding how Promise works.

Some Complexed Points

then Method Logic

then method logic is a little bit complicated, because it needs to handle the following situations:

  • if the promise is fulfilled, then the onFulfilledCallback will be executed with the value of the promise

  • if the promise is rejected, then the onRejectedCallback will be executed with the reason of the promise

  • if the promise is still pending, then the onFulfilledCallback and onRejectedCallback must be saved in an array, and executed when the status is changed

  • in order to implement the chaining of then methods, we need to return a new promise from the then method, and resolve or reject it based on the result of the onFulfilledCallback or onRejectedCallback.

Absolutely, this is a simple implementation of Promise. You can add more features to it, by the way, you can deeply understand the Promise of running progress.

0
Subscribe to my newsletter

Read articles from huabin zhang directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

huabin zhang
huabin zhang