您的当前位置:首页正文

实现Promise类,其中发现的细节

来源:花图问答

Promise 源码学习笔记

在学习Promise中让我印象最深的就是他的 .then方法,所以我非常想知道它的实现的原理。所以我到github上找了相关的实现代码。


下面是最核心的两段代码:Promise的构造函数,和then方法的定义

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;
  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);
  handle(this, new Handler(onFulfilled, onRejected, res));
  return res;
};



其中我们可以看到then方法中的
  var res = new Promise(noop);
  handle(this, new Handler(onFulfilled, onRejected, res));
  return res;

这三行代码就说明了Promise的每一次then方法都会重新构造一个Promise对象,而不是在原有对象上修改。为了证明这一点,我写了一个小demo:


var promise = new Promise(function(resolve,reject){
  resolve()
})

var a = promise
var b = promise.then(function() {
})

console.log( a === b ) //false

//证明我们的猜想是正确的


我觉得设计者这么做是因为Promise的定义,在阮一峰的相关文档中,我们可以看到

  • Promise对象有以下两个特点。(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
因为在Promise定义的回调函数是可以返回另一个Promise的,如果不新构造一个对象,那么将改变原有Promise对象的状态,这是和定义想反的。(当然这只是我的一个猜想。)

在这里不便把所有源码都展开但是可以将then函数调用其他函数的大概流程图画一下

graph LR
then-->handle
handle-->handleResovled
handleResovled-->resolve

handle函数的大概作用就是根据Promise对象回调函数的返回值,修改当前Promise对象,其中有一行关键的代码


while (self._state === 3) {
    self = self._value;
}


self代表当前Promise对象,而State === 3 代表着当前Promise对象回调函数返回值是一个Promise对象,在这里作者直接将当前Promise对象,替换成了回调函数返回的新Promise进行后续操作。


而后面两个函数大概作用就是,将回调函数返回值赋给新的Promise,就不在多说