Promise 源码解析

82 阅读7分钟
  1. 源码地址

  2. 下面通过不同的案列,跟着源码过一遍

  3. 如果想实现一个自己的promise, 实现一个promise符合A+ 的规范, 请查看

案列一


    new Promise(function(resolve, reject) {
      resolve('111')
    }).then(res => {
      console.log(res)
    })
    

简单解释

    1. 先进入doResolve 执行里面的 resolve
    2. 进入resolve, state 状态变成1 , value赋值
    3. 进入then 方法, 执行handle(this, new Handler(onFulfilled, onRejected, res));
    4. new Handler(onFulfilled, onRejected, res)) 主要判断onFulfilled, onRejected是否为函数, 并且把新创建的promise 赋值给this.promise
    5. 执行handle 里面的 handleResolved(self, deferred);
    6. asap 封装的异步,如setTimeout and queueMicrotask 等
    7. 执行tryCallOne,然后执行里面的onFulfilled 函数
    8. 再次重复resolve的这个流程,然后结束

源码解析

下面可以根据步骤来进行阅读 如 @1 @2 @3 @4 。。。。

'use strict';

var asap = require('asap/raw');

function noop() {}
 
// States:
//
// 0 - pending
// 1 - fulfilled with _value
// 2 - rejected with _value
// 3 - adopted the state of another promise, _value

var LAST_ERROR = null;
var IS_ERROR = {};
function getThen(obj) {
  try {
    return obj.then;
  } catch (ex) {
    LAST_ERROR = ex;
    return IS_ERROR;
  }
}

function tryCallOne(fn, a) {
  try {
    return fn(a);
  } catch (ex) {
    LAST_ERROR = ex;
    return IS_ERROR;
  }
}
function tryCallTwo(fn, a, b) {
  try {
    fn(a, b);
  } catch (ex) {
    LAST_ERROR = ex;
    return IS_ERROR;
  }
}

module.exports = Promise;

function Promise(fn) {
  if (typeof this !== 'object') {
    throw new TypeError('Promises must be constructed via new');
  }
  if (typeof fn !== 'function') {
    throw new TypeError('Promise constructor\'s argument is not a function');
  }
  this._deferredState = 0;
  this._state = 0;
  this._value = null;
  this._deferreds = null;
  if (fn === noop) return;
  // @1 调用函数fn
  doResolve(fn, this);
}
Promise._onHandle = null;
Promise._onReject = null;
Promise._noop = noop;

Promise.prototype.then = function(onFulfilled, onRejected) {
  if (this.constructor !== Promise) {
    return safeThen(this, onFulfilled, onRejected);
  }
  var res = new Promise(noop);
  // @6 进入then 执行下面的handle   new Handler 主要是在res上面添加了onFulfilled onRejected promise
  handle(this, new Handler(onFulfilled, onRejected, res));
  return res;
};

function safeThen(self, onFulfilled, onRejected) {
  return new self.constructor(function (resolve, reject) {
    var res = new Promise(noop);
    res.then(resolve, reject);
    handle(self, new Handler(onFulfilled, onRejected, res));
  });
}
function handle(self, deferred) {
  while (self._state === 3) {
    self = self._value;
  }
  if (Promise._onHandle) {
    Promise._onHandle(self);
  }
  if (self._state === 0) {
    if (self._deferredState === 0) {
      self._deferredState = 1;
      self._deferreds = deferred;
      return;
    }
    if (self._deferredState === 1) {
      self._deferredState = 2;
      self._deferreds = [self._deferreds, deferred];
      return;
    }
    self._deferreds.push(deferred);
    return;
  }

  // @7 状态是state === 1  直接进入到下面handleResolved 方法
  handleResolved(self, deferred);
}

function handleResolved(self, deferred) {
  // @8 asap 采用异步的 如setTimeout and queueMicrotask 等
  asap(function() {
    var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
    if (cb === null) {
      // 补充: 如果 then传进来的只是空, 默认return 当前的值 到下一个then 里面
      // 如 Promise.resolve('111').then().then(res => {console.log(res)})  会打印出 111
      if (self._state === 1) {
        resolve(deferred.promise, self._value);
      } else {
        reject(deferred.promise, self._value);
      }
      return;
    }

    // @9 当前cd 存在 执行tryCallOne  tryCallOne里面执行的函数如果报错,ret 回等于 IS_ERROR  执行下面的 reject, 否则执行resolve
    // 因为当前案列后面没有接入then, 只会再次重复执行一下resolve 的过程 
    var ret = tryCallOne(cb, self._value);
    if (ret === IS_ERROR) {
      reject(deferred.promise, LAST_ERROR);
    } else {
      resolve(deferred.promise, ret);
    }
  });
}
function resolve(self, newValue) {
  // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
  if (newValue === self) {
    return reject(
      self,
      new TypeError('A promise cannot be resolved with itself.')
    );
  }
  if (
    newValue &&
    (typeof newValue === 'object' || typeof newValue === 'function')
  ) {
    var then = getThen(newValue);
    if (then === IS_ERROR) {
      return reject(self, LAST_ERROR);
    }
    if (
      then === self.then &&
      newValue instanceof Promise
    ) {
      self._state = 3;
      self._value = newValue;
      finale(self);
      return;
    } else if (typeof then === 'function') {
      doResolve(then.bind(newValue), self);
      return;
    }
  }

  // @4  当前案列不会进入if 里面   state 变成1  fulfill,  和赋值到value
  self._state = 1;
  self._value = newValue;
  finale(self);
}

function reject(self, newValue) {
  self._state = 2;
  self._value = newValue;
  if (Promise._onReject) {
    Promise._onReject(self, newValue);
  }
  finale(self);
}
function finale(self) {
  // @5  当前案列 _deferredState还是0, 所以不会执行, 进入then
  if (self._deferredState === 1) {
    handle(self, self._deferreds);
    self._deferreds = null;
  }
  if (self._deferredState === 2) {
    for (var i = 0; i < self._deferreds.length; i++) {
      handle(self, self._deferreds[i]);
    }
    self._deferreds = null;
  }
}

function Handler(onFulfilled, onRejected, promise){
  this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
  this.onRejected = typeof onRejected === 'function' ? onRejected : null;
  this.promise = promise;
}

/**
 * Take a potentially misbehaving resolver function and make sure
 * onFulfilled and onRejected are only called once.
 *
 * Makes no guarantees about asynchrony.
 */
function doResolve(fn, promise) {
  var done = false;
  // @2  执行函数fn
  var res = tryCallTwo(fn, function (value) {
    if (done) return;
    done = true;
    // @3 执行resolve
    resolve(promise, value);
  }, function (reason) {
    if (done) return;
    done = true;
    reject(promise, reason);
  });
  if (!done && res === IS_ERROR) {
    done = true;
    reject(promise, LAST_ERROR);
  }
}

案列二

    new Promise(function (resolve, reject) {
      resolve(1);
    })
      .then((res) => {
        console.log(res);
        return new Promise(function (resolve1, reject1) {
          resolve1(res + 1);
        });
      })
      .then((res) => {
        console.log(res);
      });
    

简单解析

// 分为4个步骤

// 1. 第一个promise的执行 resolve ==》 @1 - @4
// 2. 第一个then 
      同步 ==》 @5 - @7
      异步 ==》 @10 - @15
// 3.第一个then里面的回调函数的promise的执行 ==》 @16 - @21

// 4.第二个then的执行 @8 - @9

下面是源码根据案列的步骤解析

源码解析

var asap = function (fn) {
      setTimeout(function () {
        fn();
      }, 0);
    };

    function noop() {}

    // States:
    //
    // 0 - pending
    // 1 - fulfilled with _value
    // 2 - rejected with _value
    // 3 - adopted the state of another promise, _value
    //
    // once the state is no longer pending (0) it is immutable

    // All `_` prefixed properties will be reduced to `_{random number}`
    // at build time to obfuscate them and discourage their use.
    // We don't use symbols or Object.defineProperty to fully hide them
    // because the performance isn't good enough.

    // to avoid using try/catch inside critical functions, we
    // extract them to here.
    var LAST_ERROR = null;
    var IS_ERROR = {};
    function getThen(obj) {
      try {
        return obj.then;
      } catch (ex) {
        LAST_ERROR = ex;
        return IS_ERROR;
      }
    }

    function tryCallOne(fn, a) {
      try {
        return fn(a);
      } catch (ex) {
        LAST_ERROR = ex;
        return IS_ERROR;
      }
    }
    function tryCallTwo(fn, a, b) {
      try {
        fn(a, b);
      } catch (ex) {
        LAST_ERROR = ex;
        return IS_ERROR;
      }
    }

    function Promise(fn) {
      if (typeof this !== "object") {
        throw new TypeError("Promises must be constructed via new");
      }
      if (typeof fn !== "function") {
        throw new TypeError(
          "Promise constructor's argument is not a function"
        );
      }
      this._deferredState = 0;
      this._state = 0;
      this._value = null;
      this._deferreds = null;
      if (fn === noop) return;
      // @1 调用函数fn

      // @16 重新执行第三个promise, this = 第三个promise
      doResolve(fn, this);
    }
    Promise._onHandle = null;
    Promise._onReject = null;
    Promise._noop = noop;

    Promise.prototype.then = function (onFulfilled, onRejected) {
      if (this.constructor !== Promise) {
        return safeThen(this, onFulfilled, onRejected);
      }
      var res = new Promise(noop);
      // @5 第一个then 进入,当前的this 指向的是第一个promise,

      // @8 第二个then 进入, 当前的this 指向第二个promise( 上一个then  return出来的promise)
      // 第二个promise 的状态 是默认的还是没有修改 所以 state = 0 _deferredState = 0
      handle(this, new Handler(onFulfilled, onRejected, res));

      // @7 第一个then 返回一个promise   标记为第二个promsie
      // 第一个then 里面的同步执行完成, 然后会执行第二个then,在此进入then
      return res;
    };

    function safeThen(self, onFulfilled, onRejected) {
      return new self.constructor(function (resolve, reject) {
        var res = new Promise(noop);
        res.then(resolve, reject);
        handle(self, new Handler(onFulfilled, onRejected, res));
      });
    }
    function handle(self, deferred) {
      while (self._state === 3) {
        // @14  第三个promise(第一个then函数回调的promise) 直接覆盖给了 第二个promise(第一个then 自身return出来的promsie)
        // self 指向第三个promise
        self = self._value;
      }
      if (Promise._onHandle) {
        Promise._onHandle(self);
      }
      if (self._state === 0) {
        if (self._deferredState === 0) {
          // @9 第二个then 会执行这里, 并且第二个promise状态的_deferredState = 1, 第二个promise 记录的_deferreds = onFulfilled和onRejected 和(第二个then 返回的Promise,因为下一级没的then, 不会用)
          // 第二个then 执行完成,再去执行第一个then 里面的异步handleResolved(第一个的handleResolved)

          // @15 第三个promise 的状态全是初始值,第三个promise的_deferredState = 1
          // deferreds里面包含了 第二个then 的onfulfill 和 onreject 的回调函数 请参看@13
          // 执行回调函数的(第三个promise )的流程 进入XPromise函数 重新执行一遍
          self._deferredState = 1;
          self._deferreds = deferred;
          return;
        }
        if (self._deferredState === 1) {
          self._deferredState = 2;
          self._deferreds = [self._deferreds, deferred];
          return;
        }
        self._deferreds.push(deferred);
        return;
      }

      // @6 第一个promise 在resolve 的时候状态state 已经变成了1  不会执行上面的
      // handleResolved 执行的是异步, 放在任务队列里面去, 标记为 第一个的handleResolved

      // @20 第三个promise的状态是 _state = 1 _deferredState = 1
      handleResolved(self, deferred);
    }

    function handleResolved(self, deferred) {
      asap(function () {
        var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
        if (cb === null) {
          // 补充: 如果 then传进来的只是空, 默认return 当前的值 到下一个then 里面
          // 如 Promise.resolve('111').then().then(res => {console.log(res)})  会打印出 111
          if (self._state === 1) {
            resolve(deferred.promise, self._value);
          } else {
            reject(deferred.promise, self._value);
          }
          return;
        }
        // @10 第一个promise 记录的状态_state = 1,所以执行cd = deferred.onFulfilled
        // 执行 tryCallOne, 返回的 第一个then 回调函数里面的 return出来promise  标记为: 第三个promise
        // ret = 第一个then 回调函数里面的 return出来promise  标记为: 第三个promise

        // @21  cd = 第二个then 的函数onfulfill , 执行第二个then 的回调函数
        // 下面还会去执行 reoslve, 但是没有三个then,所以只会记录第二个then 返回的promise的状态
        // 以上的执行过程 就是关于案列二 的已完成
        var ret = tryCallOne(cb, self._value);
        if (ret === IS_ERROR) {
          reject(deferred.promise, LAST_ERROR);
        } else {
          // @11 deferred 是第一个promise,  deferred.promise 是第二个promsie
          // ret 是第三个promise
          resolve(deferred.promise, ret);
        }
      });
    }
    function resolve(self, newValue) {
      if (newValue === self) {
        return reject(
          self,
          new TypeError("A promise cannot be resolved with itself.")
        );
      }
      if (
        newValue &&
        (typeof newValue === "object" || typeof newValue === "function")
      ) {
        var then = getThen(newValue);
        if (then === IS_ERROR) {
          return reject(self, LAST_ERROR);
        }
        if (then === self.then && newValue instanceof Promise) {
          // @12 当前self 指向的是第二个的promise  请参考@11
          // 第二个的promise _state = 3, _deferredState = 1 请参考@9
          // newValue 是第三个promise
          self._state = 3;
          self._value = newValue;
          finale(self);
          return;
        } else if (typeof then === "function") {
          doResolve(then.bind(newValue), self);
          return;
        }
      }

      self._state = 1;
      self._value = newValue;
      // @4 第一个promsie 执行的resolve self = 第一个promise, _state = 1, _deferredState = 0, 下面finale 函数不会进入if

      // @18 第三个promise的 _state = 1 _deferredState = 1 请参看@15
      finale(self);
    }

    function reject(self, newValue) {
      self._state = 2;
      self._value = newValue;
      if (Promise._onReject) {
        Promise._onReject(self, newValue);
      }
      finale(self);
    }
    function finale(self) {
      if (self._deferredState === 1) {
        // @13 当前self 指向的是第二个的promise   self._deferreds里面包含了 第二个then 的onfulfill 和 onreject 的回调函数

        // @19 self = 第三个promise, self._deferreds里面包含了 第二个then 的onfulfill 和 onreject 的回调函数 请参考@15
        handle(self, self._deferreds);
        self._deferreds = null;
      }
      if (self._deferredState === 2) {
        for (var i = 0; i < self._deferreds.length; i++) {
          handle(self, self._deferreds[i]);
        }
        self._deferreds = null;
      }
    }

    function Handler(onFulfilled, onRejected, promise) {
      this.onFulfilled = typeof onFulfilled === "function" ? onFulfilled : null;
      this.onRejected = typeof onRejected === "function" ? onRejected : null;
      this.promise = promise;
    }

    function doResolve(fn, promise) {
      var done = false;
      // @2  执行函数fn
      var res = tryCallTwo(
        fn,
        function (value) {
          if (done) return;
          done = true;
          // @3 执行resolve
          // @17 执行第三个promise 的 resolve
          resolve(promise, value);
        },
        function (reason) {
          if (done) return;
          done = true;
          reject(promise, reason);
        }
      );
      if (!done && res === IS_ERROR) {
        done = true;
        reject(promise, LAST_ERROR);
      }
    }