封装构造器函数
构造器函数主要用于修改实例对象状态!每个实例对象自身都有两个属性 PromiseState
和 PromiseResult
。需要明确以下几点:
- 每个实例对象只有三种状态:pending、fulfilled、rejected;
- 状态改变的方法有且只有三种:resolve函数、reject函数、抛出异常;
- 状态改变只有两种情况:由pending变为fulfilled、由pending变为rejected。
除了满足以上三个需求外,还需为实例对象指定回调函数!也就是自定义封装then方法,then方法可以接收两个参数,并且这两个参数都是作为函数被调用的,第一个函数式参数在实例对象状态为成功时被调用,而第二个则在实例对象状态为失败时被调用!并且调用时传入的参数就是实例对象成功或失败的状态值。
同步任务.js
class Promise{
constructor(executor){
// 初始化状态和状态值
this.PromiseState = 'pending';
this.PromiseResult = null;
// 保存this,由于函数内部this默认指向window
const self = this;
// 调用resolve,可以将状态修改为成功,并将接收的参数作为状态值
function resolve(data){
// 保证状态智能修改一次
if(self.PromiseState !== 'pending') return;
self.PromiseState = 'fulfilled';
self.PromiseResult = data;
};
// 调用reject,可以将状态修改为失败,并将接收的参数作为状态值
function reject(data){
if(self.PromiseState !== 'pending') return;
self.PromiseState = 'rejected';
self.PromiseResult = data;
};
// 当抛出异常时,使用try...catch修改状态
try{
executor(resolve,reject);
}catch(e){
// 可以直接调用reject函数将对象状态变为失败,此时e为失败的状态值
reject(e);
}
}
then(onResolved,onRejected){
// 状态为成功时的回调
if(this.PromiseState === 'fulfilled'){
onResolved(this.PromiseResult);
};
// 状态为失败时的回调
if(this.PromiseState === 'rejected'){
onRejected(this.PromiseResult);
}
}
}
以上封装已经能够用于实例化一个Promise对象了,但是仅适用于状态修改是同步任务的状态,一旦状态修改是异步的就不好使了。为什么呢?因为定义的then方法总只能判断状态为成功或失败两种情况的实例对象,而当状态修改是异步任务时,在指定then方法时状态并没有修改依旧是pending的状态,那实例对象就不知道该怎么办了。
解决办法是,定义then方法是需要考虑状态为pending的情况,由于状态还没有修改,只需要将指定的回调保存起来,当然保存在实例对象自身上是最稳妥的方法,这样实例对象原型上就会多了方法,作为状态改变之后执行的回调。而状态改变是通过resolve或reject函数,所以需要在这两个函数定义时判断实例对象身上是否有这两个方法,若有就说明是异步任务并且调用对应的方法!
异步任务.js
class Promise{
constructor(executor){
// 初始化状态和状态值
this.PromiseState = 'pending';
this.PromiseResult = null;
// 保存this,由于函数内部this默认指向window
const self = this;
// 定义一个空对象,用于保存回调
this.callback = {};
// 调用resolve,可以将状态修改为成功,并将接收的参数作为状态值
function resolve(data){
// 保证状态智能修改一次
if(self.PromiseState !== 'pending') return;
self.PromiseState = 'fulfilled';
self.PromiseResult = data;
// 异步任务时成功的回调
if(self.callback.onResolved){
self.callback.onResolved(data);
}
};
// 调用reject,可以将状态修改为失败,并将接收的参数作为状态值
function reject(data){
if(self.PromiseState !== 'pending') return;
self.PromiseState = 'rejected';
self.PromiseResult = data;
// 异步任务时失败的回调
if(self.callback.onRejected){
self.callback.onRejected(data);
}
};
// 当抛出异常时,使用try...catch修改状态
try{
executor(resolve,reject);
}catch(e){
// 可以直接调用reject函数将对象状态变为失败,此时e为失败的状态值
reject(e);
}
}
then(onResolved,onRejected){
// 状态为成功时的回调
if(this.PromiseState === 'fulfilled'){
onResolved(this.PromiseResult);
};
// 状态为失败时的回调
if(this.PromiseState === 'rejected'){
onRejected(this.PromiseResult);
}
// 状态为pending时,将回调保存到实例对象自身
if(this.PromiseState === 'pending'){
this.callback = {
onResolved,
onRejected
}
}
}
}
以上已经定义了一个Promise类,能够通过定义的类new出一个Promise实例对象,可以简单的测是一下。此时无论是同步还是异步修改状态,都能够得到相应的输出。接着将封装Promise函数自身的两个方法Promise.resolve()和Promise.reject()。