《Promise学习笔记》- 4Promise自定义封装之封装构造器函数

封装构造器函数

构造器函数主要用于修改实例对象状态!每个实例对象自身都有两个属性 PromiseStatePromiseResult 。需要明确以下几点:

  • 每个实例对象只有三种状态: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()。

上一篇:Promise对象


下一篇:vue中axios的封装