promise状态: pending、 fulfilled、rejected
pending转换成fulfilled与rejected状态
promise内部分装resolve与rejected方法、类公有属性status、fulfilledFns、rejectedFns、value及公有属性reason
resolve方法:赋值当前promise成功态(fulfilled)时的value值,如果promise当前状态为pending则改变当前promise状态为fulfilled 同时执行promise原型方法中then方法存储的事件集合fulilledFns
如果resolve参数为promise实例 则直接调用此参数的then方法,then方法的参数为当前promise实例中的resolve与reject方法 这样当then方法参数回调被调用之后,成功或失败的返回值则直接反映到外层当前promise中继续resolve的状态处理
reject方法:大致同resolve方法
value:会作为then方法的第一个参数回调的参数;此值在resolve()方法中确定赋值方式大致如下图代码:
reason:会作为then方法的第二个参数回调的参数;此值在resolve()方法中确定赋值方式大致如下图代码
fulfilledFns: 为then方法第一个参数的回调函数的缓存集合 场景:当一个promise实例状态为pending的时候 实例调用了then方法 这个时候promise中的value或reason还未被赋值 即then方法中的参数回调中的参数还未生成所以then方法中的参数回调不可以立即执行要进行缓存处理 可理解为fulfilledFns.push(then方法的第一个参数回调)
rejectedFns:同fulfilledFns,rejectedFns.push(then方法的第二个参数回调)
例:
function resolve(value) {
if(value instanceof Promise) {
return value.then(resolve, reject);
}
this.status = FULFILLED;
this.value = value;
this.fulfilledFns.forEach(cb => cb(this.value));
}
function reject(value) {
if(value instanceof Promise) {
return value.then(resolve, reject);
}
this.status = REJECTED;
this.reason = reason;
this.rejectedFns.forEach(cb => cb(this.value));
}
有几个情况:
情况一:promise实例调用then方法的时候,promise的state状态已经处于fulilled状态或者rejected状态
Promise.prototype.then方法的内部处理逻辑会判断当前promise实例所属状态是否为此状态如果是的话则根据state状态直接执行then方法所传的参数回调 (fulfilled状态执行第一个参数回调,rejected执行第二个参数回调)
注意在执行之前则会再次创建并返回新的promise实例 目的是为了处理then方法参数回调的返回值是promise实例的情况 同时也是为了串联调用风格 引出方法resolvePromise
if (this.status === FULFILLED) {
return newPromise = new Promise((resolve, reject) => {
setTimeout(() => {
try{
let x = onFulfilled(this.value);
resolvePromise(newPromise, x, resolve, reject);
} catch(e) {
reject(e);
}
});
})
}
if (this.status === REJECTED) {
return newPromise = new Promise((resolve, reject) => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
resolvePromise(newPromise, x, resolve, reject);
} catch(e) {
reject(e);
}
});
});
}
方法resolvePromise:
如果then方法返回值是一个非promise值(如果是一个包含then方法的对象会特殊处理 立即执行这个then)则会调用newPromise对象的resolve、reject方法将x作为参数存入newPromise的value或者reason中 后面链式调用.then().then()的时候可直接获取此x
如果方法返回值x依旧是一个promise实例并且状态为非pending的话 则会调用x.then(newPromise的resolve,newPromise的reject)方法,参数为newPromise的resolve与reject方法,直接将值暴露外层。
如果方法返回值x是一个promise实例并且状态为pending的话 则会调用x.then((y)=>{resolvePromise(newPromise,x,resolve,reject)})运用递归将方法存入fulfilledFns方法集合中等待此promise状态为非pending时执行方法 由于此resolve为newPromise的resolve则链式调用的then方法即newPromise.__proto__.then中参数为x返回的promise中的value 即调用x中的resolve方法赋值的value x中的resolve触发调用之后会触发newPromise.__proto__.then参数回调 从而获取x中的value实现链式调用
function resolvePromise(promise2, x, resolve, reject) {
if (x instanceof Promise) {
if (x.status === PENDING) {
x.then(y => {
resolvePromise(promise2, y, resolve, reject);
}, reason => {
reject(reason);
});
} else {
x.then(resolve, reject);
}
} else if (x != null && ((typeof x === 'object') || (typeof x === 'function'))) {
try {
resolve(x);
} catch(e) {
if(called) return;
reject(e);
}
} else {
resolve(x);
}
}
情况二:promise实例调用then方法的时候,promise的state状态依然处于pending状态
则此then方法的返回值promise会将即将执行的then方法的参数及其他处理逻辑包裹一层回调函数push进入fulfilledFns集合中等待promise状态被resolve或reject方法改变之后调用fulfilled集合执行then方法的参数回调函数并根据then方法的参数回调函数的返回值进一步调用resolvePromise来处理 逻辑同上 例:
if (that.status === PENDING) {
return newPromise = new Promise((resolve, reject) => {
that.fulfilledFns.push((value) => {
try {
let x = onFulfilled(value);//then(onFulfilled,onRejected)
resolvePromise(newPromise, x, resolve, reject);
} catch(e) {
reject(e);
}
});
that.rejectedFns.push((reason) => {
try {
let x = onRejected(reason);
resolvePromise(newPromise, x, resolve, reject);
} catch(e) {
reject(e);
}
});
});
}
说白了promise就是各种回调的组合 以及方法集合的合理存储