前面3篇文章深入讲解了 Promise A+ 规范之基本介绍、 Promise A+规范之Promise解决过程、高级开发者必须掌握的手写Promise(一),建议看这篇之前必须去把上面三篇文章看懂,否则很难看懂此文~
本篇文章主要是实现Promise A+规范之Promise解决过程~
一、Promise 解决过程规范
Promise 解决过程 是一个抽象的操作,其需输入一个 promise 和一个值,我们表示为 [[Resolve]](promise, x),如果 x 有 then 方法且看上去像一个 Promise ,解决程序即尝试使 promise 接受 x 的状态;否则其用 x 的值来执行 promise 。
这种 thenable 的特性使得 Promise 的实现更具有通用性:只要其暴露出一个遵循 Promise/A+ 协议的 then 方法即可;这同时也使遵循 Promise/A+ 规范的实现可以与那些不太规范但可用的实现能良好共存。
运行 [[Resolve]](promise, x) 需遵循以下步骤:
x 与 promise 相等
如果 promise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 promise
x 为 Promise
如果 x 为 Promise ,则使 promise 接受 x 的状态 注4:
- 如果
x处于等待态,promise需保持为等待态直至x被执行或拒绝 - 如果
x处于执行态,用相同的值执行promise - 如果
x处于拒绝态,用相同的据因拒绝promise
x 为对象或函数
如果 x 为对象或者函数:
-
把
x.then赋值给then注5 -
如果取
x.then的值时抛出错误e,则以e为据因拒绝promise -
如果
then是函数,将x作为函数的作用域this调用之。传递两个回调函数作为参数,第一个参数叫做resolvePromise,第二个参数叫做rejectPromise:-
如果
resolvePromise以值y为参数被调用,则运行[[Resolve]](promise, y) -
如果
rejectPromise以据因r为参数被调用,则以据因r拒绝promise -
如果
resolvePromise和rejectPromise均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用 -
如果调用
then方法抛出了异常e:- 如果
resolvePromise或rejectPromise已经被调用,则忽略之 - 否则以
e为据因拒绝promise
- 如果
-
如果
then不是函数,以x为参数执行promise
-
-
如果
x不为对象或者函数,以x为参数执行promise
二、主要功能讲解
- then返回一个Promise对象
promise2 = promise1.then(onFulfilled, onRejected);
-
onFulfilled可能返回普通值、promise对象等
-
onRejected可能返回普通值、promise对象等
-
catch的实现
三、 具体实现
(1)then返回一个Promise对象
then(onFulfilled, onRejected) {
let promise2 = new localPromise((resolve, reject) => {
if(this.state === STATUS.FULFILLED) {
let x = onFulfilled(this.value)
}
//以下代码省略......
});
return promise2;
}
(2)实现Promise 解决过程
then(onFulfilled, onRejected) {
let promise2 = new localPromise((resolve, reject) => {
if(this.state === STATUS.FULFILLED) {
let x = onFulfilled(this.value)
setTimeout(() => { //使用异步代码的原因是确保promise2必须初始化完成
resolvePromise(promise2, x, resolve, reject); //Promise 解决过程
}, 0)
}
if(this.state === STATUS.REJECTED) {
let x = onFulfilled(this.reason)
setTimeout(() => {
resolvePromise(promise2, x, resolve, reject); //Promise 解决过程
}, 0)
}
if (onFulfilled && isFunction(onFulfilled)) {
//将onFulfilled回调存储在onFulfilledCallbacks中
this.onFulfilledCallbacks.push(() => {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject); //Promise 解决过程
});
}
if (onRejected && isFunction(onRejected)) {
//将onFulfilled回调存储在onFulfilledCallbacks中
this.onRejectedCallbacks.push(() => {
let x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject); //Promise 解决过程
});
}
});
return promise2;
}
(3)resolvePromise(promise2, x, resolve, reject)
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {//如果 promise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 promise
reject(new TypeError("Chaining cycle detected for promise #<localPromise>"));
} if (x instanceof localPromise && x != promise2) { //如果 x 为 Promise ,则使 promise 接受 x 的状态
try {
// resolve(`x instanceof localPromise`);
x.then(value => {
resolve(value);
}, reject => {
reject(reject);
});
} catch (e) {
console.log(`x.then`, e)
}
} if(x instanceof Object || typeof x === 'function') { //x 为对象或函数
try {
then = x.then; //把 x.then 赋值给 then
if(typeof then === 'function') {
//如果 `then` 是函数,将 `x` 作为函数的作用域 `this` 调用之。
//传递两个回调函数作为参数
then.call(x, (y) => {
//如果 `resolvePromise` 以值 `y` 为参数被调用,则运行 `[[Resolve]](promise, y)`
resolvePromise(promise2, y, resolve, reject);
}, (r) => {
//如果 `rejectPromise` 以据因 `r` 为参数被调用,则以据因 `r` 拒绝 `promise`
reject(y)
})
} else { //如果 `then` 不是函数,以 `x` 为参数执行 `promise`
resolve(x);
}
} catch (e) {
reject(e); //如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise
}
} else {//如果 `x` 不为对象或者函数,以 `x` 为参数执行 `promise`
resolve(x);
}
}
(4)catch的实现
catch其实就是then(null, onRejected)
catch(errorCallbacks) {
return this.then(null, errorCallbacks);
}
对onFulfilled, onRejected非函数的处理
- 如果
onFulfilled不是函数且promise1成功执行,promise2必须成功执行并返回相同的值 - 如果
onRejected不是函数且promise1拒绝执行,promise2必须拒绝执行并返回相同的据因
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => { value }
onRejected = typeof onRejected === 'function' ? onRejected : (reason) => { throw reason}
四、完整源码
//状态枚举
const STATUS = {
PENDING: 'PENDING',
FULFILLED: 'FULFILLED',
REJECTED: 'REJECTED'
}
class localPromise {
constructor(executor) {
//最初始状态
this.state = STATUS.PENDING;
this.value = undefined; //值或者终值
this.reason = undefined; //拒因或者失败原因
//存储异步回调,为啥用数组,是因为promise实例可以多次调then,
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
const resolve = function (value) { // resolve函数,功能是扭转状态为fulFilled&设置终值
if (this.state === STATUS.PENDING) {
this.state = STATUS.FULFILLED;
this.value = value;
console.log('执行resolve', value);
this.onFulfilledCallbacks.forEach(cb => {
cb();
});
}
}.bind(this)
const reject = function (reason) { // reject函数,功能是扭转状态为rejected&设置拒因
if (this.state === STATUS.PENDING) {
this.state = STATUS.REJECTED;
this.reason = reason;
console.log('执行reject', reason);
this.onRejectedCallbacks.forEach(cb => {
cb();
});
}
}.bind(this)
try { //捕获异常,并执行reject,保存错误的时候扭转状态为rejected&设置拒因
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
//接受两个参数 onFulfilled和onRejected
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => { value }
onRejected = typeof onRejected === 'function' ? onRejected : (reason) => { throw reason}
let promise2 = new localPromise((resolve, reject) => {
console.log(this.state);
if(this.state === STATUS.FULFILLED) {
let x = onFulfilled(this.value)
setTimeout(() => {
resolvePromise(promise2, x, resolve, reject);
}, 0)
}
if(this.state === STATUS.REJECTED) {
let x = onFulfilled(this.reason)
resolvePromise(promise2, x, resolve, reject);
}
if (this.state === STATUS.PENDING) {
//将onFulfilled回调存储在onFulfilledCallbacks中
this.onFulfilledCallbacks.push(() => {
let x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
});
}
});
return promise2;
}
catch(errorCallback) {
return this.then(null, errorCallback);
}
}
function isFunction(value) {
return typeof value === 'function' && typeof value.nodeType !== 'number';
}
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {//如果 promise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 promise
reject(new TypeError("Chaining cycle detected for promise #<localPromise>"));
} if (x instanceof localPromise && x != promise2) { //如果 x 为 Promise ,则使 promise 接受 x 的状态
try {
// resolve(`x instanceof localPromise`);
x.then(value => {
resolve(value);
}, reject => {
reject(reject);
});
} catch (e) {
console.log(`x.then`, e)
}
} if(x instanceof Object || typeof x === 'function') { //x 为对象或函数
let then;
try {
then = x.then; //把 x.then 赋值给 then
if(typeof then === 'function') {//如果 then 是函数,
then.call(x, (y) => {
resolvePromise(promise2, y, resolve, reject);
}, (r) => {
reject(y)
})
} else {
resolve(x);
}
} catch (e) {
reject(e); //如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise
}
} else {
resolve(x);
}
}