A promise library in ES6 for learning Promise/A+ Specification.
- 模仿了Adehun的实现
- 通过了promises-aplus-tests所有测试用例
npm install & npm run test
在实现过程中,参考Promise/A+规范,我们把Promise抽象成以下模块。
then方法是规范中定义的方法,同时也应该是Promise最重要的标识,主要特点如下:
- then方法接受两个可选参数: onFulfilled, onRejected
- then方法必须返回一个promise
then(onFulfilled, onRejected) {
const queuedPromise = new Lamb();
if (Utils.isFunction(onFulfilled)) {
queuedPromise.handlers.onFulfilled = onFulfilled;
}
if (Utils.isFunction(onRejected)) {
queuedPromise.handlers.onRejected = onRejected;
}
this.queue.push(queuedPromise);
this.process();
return queuedPromise;
}
transition
方法检查promise
当前state
的合法性并更新其state
和value
,并将接下来的处理交给process
方法。
transition(state, value) {
if (this.state === state || this.state !== VALIDATE_STATE.PENDING || !Utils.isValidateState(state) ||
arguments.length !== 2) {
return;
}
this.state = state;
this.value = value;
this.process();
}
- 我们知道当一个promise(姑且将这个promise叫做
base promise
)的then方法执行时,then方法创建的新的promise(queuedPromise
)会被push到base promise
的pending queue中。 - transiton方法执行后,
base promise
的state
和value
更新 - then方法执行后,
base promise
的pending queue
push 新的queuedPromise
- process方法会在then方法和transition方法中被调用,处理后续流程。
process() {
if (this.state === VALIDATE_STATE.PENDING) {
return;
}
const that = this;
// 2.2.4 onFulfilled or onRejected must not be called until the execution context stack contains only platform code.
Utils.runAsync(() => {
while (that.queue && that.queue.length) {
const queuedPromise = that.queue.shift();
let handler = null;
let value = null;
if (that.state === VALIDATE_STATE.FULFILLED) {
handler = queuedPromise.handlers.onFulfilled || Utils.defaultFulfillCallback;
} else if (that.state === VALIDATE_STATE.REJECTED) {
handler = queuedPromise.handlers.onRejected || Utils.defaultRejectCallback;
}
try {
value = handler(that.value);
} catch (e) {
queuedPromise.transition(VALIDATE_STATE.REJECTED, e);
continue;
}
resolve(queuedPromise, value);
}
});
}
Process runs the Promise Resolution procedure on all internally stored promises (i.e. those that were attached to the base promise through the then function) and enforces the following Promise/A+
resolve
可能是promise最核心的模块,它处理promise的“解决”(resolve
)过程。依照Promise/A+规范的定义,resolve
方法的形式为: [[Resolve]](promise, x)
。
const resolve = (x) => {
if (x === this) {
// 当需要resolve的x是当前promise的时候,直接reject,并抛出TypeError异常
promise.transition(VALIDATE_STATE.REJECTED, new TypeError('The promise and its value refer to the same object.'));
} else if (Utils.isPromise(x)) {
// 当x的类型是promise且非当前promise时,根据x的state进行相应处理
if (x.state === VALIDATE_STATE.PENDING) {
// 若x的state为pending时,当前promise的resolve被延迟
x.then(value => resolve(this, value), reason => this.transition(VALIDATE_STATE.REJECTED, reason));
} else {
// 若x的state为fulfilled或者rejected,则使用x的state和value应用于当前promise
this.transition(x.state, x.value);
}
} else if (Utils.isObject(x) || Utils.isFunction(x)) {
// 若x的类型为Ojbect或者function时(thenable),检查该对象上是否有then方法
let then = null;
let isCalled = false;
try {
then = x.then;
if (Utils.isFunction(then)) {
then.call(x, (value) => {
if (!isCalled) {
resolve(this, value);
isCalled = true;
}
}, (reason) => {
if (!isCalled) {
this.reject(reason);
isCalled = true;
}
});
} else {
this.fulfill(x);
isCalled = true;
}
} catch (e) {
if (!isCalled) {
this.reject(e);
isCalled = true;
}
}
} else {
this.fulfill(x);
}
};
- 根据Promis/A+规范Promise有3个状态:
PENDING
,FULFILLED(settled)
,REJECTED(settled)
。 - 处于
FULFILLED
和REJECTED
状态的promise
,其状态不能再进行转移。
const VALIDATE_STATE = {
PENDING: 0,
FULFILLED: 1,
REJECTED: 2,
};
const Utils = {
// 异步执行帮助函数
runAsync: (fn) => {
setTimeout(fn, 0);
},
// 判断一个值是否是promise类型
isPromise: p => p && p instanceof Lamb,
// 判断一个值是否是对象类型
isObject: value => value && typeof value === 'object',
// 判断一个值是否是函数类型
isFunction: value => value && typeof value === 'function',
// 默认的`fulfill`函数
defaultFulfillCallback: value => value,
// 默认的`reject`函数
defaultRejectCallback: (reason) => { throw reason; },
// 判断一个状态是否是合法的promise状态
isValidateState: state => (state === VALIDATE_STATE.PENDING) || (state === VALIDATE_STATE.FULFILLED) ||
(state || VALIDATE_STATE.REJECTED),
};
fulfill
和reject
分别会将当前promise
的状态转移到settled(fulfilled or rejected)
状态,并交由transition
方法进行后续处理
reject(reason) {
this.transition(VALIDATE_STATE.REJECTED, reason);
}
fulfill(value) {
this.transition(VALIDATE_STATE.FULFILLED, value);
}