源码开头
//
// 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.
- 有 0-3 四种状态,分别对应,创建初始化、成功响应、异常响应、响应了一个Promise
- 选择在私有属性上使用 ‘_’ + 随机数作为前缀,这样比其他方式性能好
准备工作
var asap = require('asap');
function noop() {}
// 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;
}
}
- 引入了异步包asap
- 函数式的noop
- 用于触发 Then 监听方法的 tryCallOne
- 用于捕获 resolve、reject 的 tryCallTwo
- 捕获获取then方法可能的异常,在判断响应值是否是promise时使用,应对不同人写的符合特征的promise
使用new Promise(execute(resolve, reject))时
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._U = 0;
this._V = 0;
this._W = null;
this._X = null;
if (fn === noop) return;
doResolve(fn, this);
}
- 参数校验
- V是状态,对应源码开头提到的4种
- U是监听/等待的状态,0是没有,1是一个,2是超过一个
- W是返回值
- X是监听者,按照U的情况,值的范围:单个回调方法 / 回调方法集合数组
- noop完成了职责
doResolve
/**
* 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;
var res = tryCallTwo(fn, function (value) {
if (done) return;
done = true;
resolve(promise, value);
}, function (reason) {
if (done) return;
done = true;
reject(promise, reason);
});
if (!done && res === IS_ERROR) {
done = true;
reject(promise, LAST_ERROR);
}
}
- 调用传入的方法 execute, 并且传入 resolve, reject
- 在方法异常或者方法主动调用reject外的情况调用resolve
- 用done变量防止重复调用
resolve
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._V = 3;
self._W = newValue;
finale(self);
return;
} else if (typeof then === 'function') {
doResolve(then.bind(newValue), self);
return;
}
}
self._V = 1;
self._W = newValue;
finale(self);
}
- 先防止响应的数据是自身这个Promise, 防止死循环
- 然后对于响应值是Promise的情况进行兼容
- 如果是不合规的Promise,响应异常,触发reject
- 如果是自身同源Promise,状态变为3,填充响应值
- 如果是他人写的Promise,触发他的Then方法,填充响应值
- 如果以上都不是,修改自身状态为已完成,填充响应值,触发finale
reject
function reject(self, newValue) {
self._V = 2;
self._W = newValue;
if (Promise._Z) {
Promise._Z(self, newValue);
}
finale(self);
}
- 忽略Promise._Z,这是一个联动逻辑
- 修改自身状态为已失败,填充异常值,触发finale
finale
function finale(self) {
if (self._U === 1) {
handle(self, self._X);
self._X = null;
}
if (self._U === 2) {
for (var i = 0; i < self._X.length; i++) {
handle(self, self._X[i]);
}
self._X = null;
}
}
- 判断一下接受响应的数目状态,最后都是交与handle处理
调用 promise.then() 时
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;
};
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 Handler(onFulfilled, onRejected, promise){
this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
this.onRejected = typeof onRejected === 'function' ? onRejected : null;
this.promise = promise;
}
- var res = new Promise(noop); 创造了一个不会变化的Promise
- 然后就简单返回noop的promise
- 如果then方法触发时不在自身,就用自身包裹一下再返回,目的是延后这个操作,等其他人写的Promise先执行
handle
function handle(self, deferred) {
while (self._V === 3) {
self = self._W;
}
if (Promise._Y) {
Promise._Y(self);
}
if (self._V === 0) {
if (self._U === 0) {
self._U = 1;
self._X = deferred;
return;
}
if (self._U === 1) {
self._U = 2;
self._X = [self._X, deferred];
return;
}
self._X.push(deferred);
return;
}
handleResolved(self, deferred);
}
- 如果响应值是Promise,就用循环拆包
- 忽略 Promise._Y,联动处理
- 如果then时,还没有结果可以响应,就填入等待 对象/数组
- 这里在多次调用中调整 U 的值,deferred存储等待触发的接收方法
- 如果已经 完成/失败 直接触发 handleResolved
handleResolved
function handleResolved(self, deferred) {
asap(function() {
var cb = self._V === 1 ? deferred.onFulfilled : deferred.onRejected;
if (cb === null) {
if (self._V === 1) {
resolve(deferred.promise, self._W);
} else {
reject(deferred.promise, self._W);
}
return;
}
var ret = tryCallOne(cb, self._W);
if (ret === IS_ERROR) {
reject(deferred.promise, LAST_ERROR);
} else {
resolve(deferred.promise, ret);
}
});
}
- 用 asap 统一化了异步调用,意味着用Promise包装同步方法,也会异步执行
- 用 asap 有一个好处,监听者很多时,不会造成执行的占用,每一个监听都是一次处理
- 判断自身状态去触发 then/catch 方法
- 触发之前 noop版promise的响应,也就是触发链式的Then/catch
收尾
因为有递归在里面,初看时没注意差点被绕进去,不过本身还是比想象简单。