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函数调用其他函数的过程写下来
then-->handle-->handleResovled-->resolve
handle函数的大概作用就是根据Promise对象回调函数的返回值,修改当前Promise对象,其中有一行关键的代码
while (self._state === 3) {
self = self._value;
}
self代表当前Promise对象,而State === 3 代表着当前Promise对象回调函数返回值是一个Promise对象,在这里作者直接将当前Promise对象,替换成了回调函数返回的新Promise进行后续操作。
而后面两个函数大概作用就是,将回调函数返回值赋给新的Promise,就不在多说