promise polyfill解析

https://github.com/taylorhakes/promise-polyfill

Promise构造器

function Promise(fn) {
  if (!(this instanceof Promise))
    throw new TypeError('Promises must be constructed via new');
  if (typeof fn !== 'function') throw new TypeError('not a function');
  /**
   * 0: pending
   * 1: resolve
   * 2: reject
   * 3: res(p)中p为promise类型
   */
  this._state = 0;
  /** 是否处理完成 */
  this._handled = false;
  /** 当前promise的value值 */
  this._value = undefined;
  /** 保存obj,obj包含3个参数:
   * 当前promise的onFulfilled和onRejected回调方法
   * 当前promise的完成后要执行的promise
  */
  this._deferreds = [];doResolve(fn, this);
}

doResolve

执行Promise构造时的参数。且如果执行出错,则直接reject

new Promise((res, rej) => {
  setTimeout(() => {
    res();
  }, 0)
});function doResolve(fn, self) {
  var done = false;
  try {
    fn(
      // 上面代码中res()时执行
      function(value) {
        if (done) return;
        done = true;
        resolve(self, value);
      },
      // 上面代码中rej()时执行
      function(reason) {
        if (done) return;
        done = true;
        reject(self, reason);
      }
    );
  } catch (ex) {
    if (done) return;
    done = true;
    reject(self, ex);
  }
}

可以看到是同步执行的,所以下面代码依次输出1,2,3

new Promise(() => {
  console.log(1);
});
console.log(2);
setTimeout(() => {
  console.log(3);
}, 0);

then

Promise.prototype.then = function(onFulfilled, onRejected) {
  var prom = new this.constructor(noop);
  // handler存储调用then的promise及then的参数
  var handler = new Handler(onFulfilled, onRejected, prom);
  handle(this, handler);
  // 返回prom,即下一个then的this对象
  return prom;
};
​
​
function Handler(onFulfilled, onRejected, promise) {
  this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
  this.onRejected = typeof onRejected === 'function' ? onRejected : null;
  this.promise = promise;
}

handle

根据当前promise的状态处理:

当前promise的值是promise,则取最内层的promise值为作为当前promise

当前promise为pending状态,将其调用then时then的参数及自身存到自己的_deferreds上,所以then return prom会在then的调用链上形成promise内有_deferreds,_deferreds内有promise的循环

当前promise为resolve(1)或reject(2)状态,取对应的回调执行

function handle(self, deferred) {
  while (self._state === 3) {
    self = self._value;
  }
  // 将then的参数存放在then的调用者的_deferreds中
  if (self._state === 0) {
    self._deferreds.push(deferred);
    return;
  }
  self._handled = true;
  // resolve后当前promise的状态为1,reject后为2,且要在下个事件循环中完成回调
  Promise._immediateFn(function() {
    var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
    if (cb === null) {
      (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
      return;
    }
    var ret;
    try {
      ret = cb(self._value);
    } catch (e) {
      reject(deferred.promise, e);
      return;
    }
    // deferred.promise:取deferred上的promise,及下一个then的调用者
    resolve(deferred.promise, ret);
  });
}

resolve

关键代码:

将当前promise的状态改为1(resolve),执行final,

self._state = 1;
self._value = newValue;
finale(self);
function finale(self) {
  if (self._state === 2 && self._deferreds.length === 0) {
    Promise._immediateFn(function() {
      if (!self._handled) {
        Promise._unhandledRejectionFn(self._value);
      }
    });
  }
  // 取当前promise的_deferreds,处理当前promise的状态
  for (var i = 0, len = self._deferreds.length; i < len; i++) {
    handle(self, self._deferreds[i]);
  }
  self._deferreds = null;
}

Promise的就是根据状态进行处理的过程​​,最关键的是then方法的返回参数并不是this,因为每个then或catch的状态需要分开处理

new Promise((res) => { res(); })  // p1
.then(f1)  // p2
.then(f2)  // p3

将上面代码中调用每行then的promise实例分别标记为p1,p2,p3,当然p1自己就是promise

p2对应的line执行时,调用者是p1,在p1实例的_deferreds中存储f1和p2的实例,且返回p2

p3对应的line执行时,调用者是p2,所以在p2实例的_deferreds中存储f2和p3的实例,且返回p3

这样保证每个then或catch的状态不会收其他promise的影响
promise polyfill解析_第1张图片

你可能感兴趣的:(javascript)