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

2018-09-26  本文已影响13人  strong9527

Promise 源码学习笔记

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

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定义的回调函数是可以返回另一个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,就不在多说

上一篇下一篇

猜你喜欢

热点阅读