手写Promise

42 阅读5分钟

Promise是JavaScript的一个重点,本文主要记录我手写ES6 Promise的思路,仅实现Promise及其.then方法,最下方附带完整代码,希望对你有所帮助

Promise

在传统的项目中,使用异步操作只能不断地通过callback来进行回调,在复杂的项目中就容易产生回调地狱的问题,这时候ES6引入了几个异步解决方案,其中Promise就包含其中,极大地改善了异步操作

Promise/A+中并未规范race、all等方法,这些都是ES6的规范,本文主要实现Promise构建及其.then方法

手写Promise

promise对象接收的是callback,callback接收两个参数resolve和reject 当我们在执行callback的时候,会调用定义的resolve和reject,这两个函数需要我们定义在Promise内部 然后resolve和reject会改变promise的状态,我们需要一个state来记录当前promise的状态

function MyPromise(callback){
  let self = this;

  let state = null;//null表示pending,false表示rejected,true表示fulfilled

  //保留Promise完成时的结果值或者错误信息,让他在后续还能用上
  let param = null;
  
   //resolve方法
  function resolve(data) {
    state = true;
    param = data;
  }

  

  //reject方法
  function reject(data) {
    state = false;
    param = data;
  }
}

但是我们这里缺少了Promise的重要内容then方法 then方法接收的参数为onFulfilled和onRejected,都为可选参数,在期约分别进入兑现和拒绝状态时执行,在规范中提到传进来的参数只能是函数,如果想要跳过某一个参数可以先传入null then方法返回的也是一个Promise对象,这是链式调用的核心

  //then方法
  this.then = function (onFulfilled, onRejected) {
    //返回一个新的promise对象,链式调用的核心
    return new self.constructor(function (resolve, reject) {
      ......
    });

  };

then方法的实现 这时候需要根据状态进行判断执行哪个函数,但是如果为pending状态呢 Promise的状态我们无法实时获取,因此我们只能在执行状态改变的时候,也就是在resolve和reject两个方法中,同时执行onFulfilled或者onRejected,但是我们这里没有这两个函数,所以需要在外部增加四个变量分别记录onFulfilledonRejected,以及then方法返回的新promise对象的resolvereject

function MyPromise(callback) {
  ........
  //then方法返回的promise对象的resolve和rejectlet nextResolve = null;
+  let nextReject = null;

  //记录then方法的回调函数let asynconFulfilled = null;
+  let asynconRejected = null;
  
  //执行并改变promise对象状态
  callback(resolve, reject);
  
  //then方法
  this.then = function (onFulfilled, onRejected) {
    //返回一个新的promise对象,链式调用的核心
    return new self.constructor(function (resolve, reject) {
+      //判断异步代码是否执行完毕
+      //若执行完毕就在then方法中立即执行,否则将四个参数记录下来,等待state就绪后再执行
+      if (state === true) {
+        doAsynconFulfilled(onFulfilled, resolve, reject);
+      } else if (state === false) {
+        doAsynconRejected(onRejected, resolve, reject);
+      } else {
+        nextResolve = resolve;
+        nextReject = reject;
+        asynconFulfilled = onFulfilled;
+        asynconRejected = onRejected;
+      }
    });
  };

  //resolve方法
  function resolve(data) {
    state = true;
    param = data;
+    nextResolve(asynconFulfilled(param))
  }

  //reject方法
  function reject(data) {
    state = false;
    param = data;
+    nextReject(asynconRejected(param))
  }
}

这里我画个图可能会更好理解一点

屏幕截图 2025-08-10 130221.png

其实就两个时间线:then 在 resolve 之前 调用(pending 状态),then 在 resolve 之后 调用(fulfilled/rejected 状态)

但是我们少判断了一点,如果then返回的为promise对象,如果后面还有then方法需要等待前一个then中的prmise状态变为兑现活拒绝,才能执行 这里传入的onFulfilled和onRejected和then方法传进来的参数必须为函数,如果不是则忽略掉

//resolve方法
  function resolve(data) {
    state = true;
    param = data;
    if (nextResolve) {
      doAsynconFulfilled(asynconFulfilled, nextResolve, nextReject);
    }
  }

  //reject方法
  function reject(data) {
    state = false;
    param = data;
    if (nextReject) {
      doAsynconRejected(asynconRejected, nextResolve, nextReject);
    }
  }

  function doAsynconFulfilled(onFulfilled, resolve, reject) {
    //onFulfilled和onRejected只有再执行环境堆栈仅包含平台代码时才可被调用,将其放在setTimeout中执行
    //平台代码指的是JavaScript宿主环境(如nodejs或浏览器)提供的代码(比如setTimeout),而非用户定义的代码
    //确保then回调总是异步执行,及时Promise是同步resolved或rejected
    window.setTimeout(function () {
      //判断onFulfilled是否为函数,不是则忽略
      if (typeof onFulfilled === "function") {
        let promise = onFulfilled(param);
        if (promise === undefined) {
          //如果没有显式返回语句,Promise.resolve会包装默认的返回值undefined
          //如果onFulfilled没有返回值,则直接resolve
          resolve(promise);
        } else if (promise.constructor === self.constructor) {
          //等待传递进行的promise执行完毕,再根据传递进行的promise的状态来决定是resolve还是reject
          promise.then(
            function (param) {
              resolve(param);
            },
            function (param) {
              reject(param)
            }
          );
        } else {
          //执行then方法返回的对象的resolve方法
          resolve(promise);
        }
      } else {
        //传递参数
        resolve(param);
      }
    }, 0);
  }

  function doAsynconRejected(onRejected, resolve, reject) {
    window.setTimeout(function () {
      if (typeof onRejected === "function") {
        let promise = onRejected(param);
        if (promise === undefined) {
          reject(param);
        } else if (promise.constructor === self.constructor) {
          promise.then(
            function (param) {
              resolve(param);
            },
            function (param) {
              reject(param);
            }
          );
        } else {
          reject(promise);
        }
      } else {
        //传递参数
        reject(param);
      }
    }, 0);
  }

最终代码

function MyPromise(callback) {

  let self = this;

  let state = null;

  //记录resolve的参数

  let param = null;

  //then方法返回的promise对象的resolve和reject

  let nextResolve = null;

  let nextReject = null;

  //记录then方法的回调函数

  let asynconFulfilled = null;

  let asynconRejected = null;

  

  //执行并改变promise对象状态

  callback(resolve, reject);

  //then方法

  this.then = function (onFulfilled, onRejected) {

    //返回一个新的promise对象,链式调用的核心

    return new self.constructor(function (resolve, reject) {

      //判断异步代码是否执行完毕

      //若执行完毕就在then方法中立即执行,否则将四个参数记录下来,等待state就绪后再执行doAsyn函数

      if (state === true) {

        doAsynconFulfilled(onFulfilled, resolve, reject);

      } else if (state === false) {

        doAsynconRejected(onRejected, resolve, reject);

      } else {

        nextResolve = resolve;

        nextReject = reject;

        asynconFulfilled = onFulfilled;

        asynconRejected = onRejected;

      }

    });

  };

  

  //resolve方法

  function resolve(data) {

    state = true;

    param = data;

    if (nextResolve) {

      doAsynconFulfilled(asynconFulfilled, nextResolve, nextReject);

    }

  }

  

  //reject方法

  function reject(data) {

    state = false;

    param = data;

    if (nextReject) {

      doAsynconRejected(asynconRejected, nextResolve, nextReject);

    }

  }

  

  function doAsynconFulfilled(onFulfilled, resolve, reject) {

    //onFulfilled和onRejected只有再执行环境堆栈仅包含平台代码时才可被调用,将其放在setTimeout中执行

    //平台代码指的是JavaScript宿主环境(如nodejs或浏览器)提供的代码(比如setTimeout),而非用户定义的代码

    //确保then回调总是异步执行,及时Promise是同步resolved或rejected

    window.setTimeout(function () {

      //判断onFulfilled是否为函数,不是则忽略

      if (typeof onFulfilled === "function") {

        let promise = onFulfilled(param);

        if (promise === undefined) {

          //如果没有显式返回语句,Promise.resolve会包装默认的返回值undefined

          //如果onFulfilled没有返回值,则直接resolve

          resolve(promise);

        } else if (promise.constructor === self.constructor) {

          //等待传递进行的promise执行完毕,再根据传递进行的promise的状态来决定是resolve还是reject

          promise.then(

            function (param) {

              resolve(param);

            },

            function (param) {

              reject(param);

            }

          );

        } else {

          //执行then方法返回的对象的resolve方法

          resolve(promise);

        }

      } else {

        //传递参数

        resolve(param);

      }

    }, 0);

  }

  

  function doAsynconRejected(onRejected, resolve, reject) {

    window.setTimeout(function () {

      if (typeof onRejected === "function") {

        let promise = onRejected(param);

        if (promise === undefined) {

          reject(param);

        } else if (promise.constructor === self.constructor) {

          promise.then(

            function (param) {

              resolve(param);

            },

            function (param) {

              reject(param);

            }

          );

        } else {

          reject(promise);

        }

      } else {

        //传递参数

        reject(param);

      }

    }, 0);

  }

}