实现一个简版的 Promise

207 阅读4分钟

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操 作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise提供 统一的 API,各种异步操作都可以用同样的方法进行处理。

Promise对象有以下两个特点。

(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态: Pending(进行中)、Resolved(已完成,又称Fulfilled)和Rejected(已失败)。 只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。 这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变, 只有两种可能:从Pending变为Resolved和从Pending变为Rejected只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是, 如果你错过了它,再去监听,是得不到结果的。 有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调 函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。


我们今天来实现一个简版的 Promise

首先我要会用 Promise 那么我们先来用一下吧 看下面的例子

 (1-1-1)
   let promise = new Promise((resolve, reject)=>{
        // todo 当我在这里处理一些问题时 控制 promise 的状态 
        // 是让它为 成功态 还是 失败态 这里由 我们自己的业务逻辑所决定
        
        // 这里只做调用演示 resolve, reject二者只能调用一个
        resolve('成功啦,开心'); 
        
        // 这里只做调用演示 resolve, reject二者只能调用一个
        reject('失败了,懊恼'); 
        
   }).then((res)=>{
      console.log(res)
   },(err)=>{
      console.log(err)
   });

看过上面的例子我们对 Promise 的应该是了解的,所以不啰嗦,开始撸实现代码;

那么大家看上面例子这里 Promise 是通过new一个实例的方式创建的那么这个Promise是一个类

  • 1.首先我要写一个 promise 类
  • 2.这个类 在 new的过程中会传入一个默认的执行方法executor然后执行
  • 3.这个默认执行方法会有两个参数 resolve, reject (这里注意下 这个两个参数是每一个promise的私有方法)
  • 4.给我们promise 增加状态,成功态(resolve)| 失败态(reject)| 等待态(pending)默认是 pending
const RESOLVE = "RESOLVE";
const REJECT = "REJECT";
const PENDING = "PENDING";

class Promise {
    constructor(executor){
        this.status = PENDING;
        let resolve = ()=>{
        };
        let reject = ()=>{
        };
        executor(resolve, reject);
    }
}

当设置这个 Promise 为成功态的就会调用resolve方法 就是上面(1-1-1)例子的调用形式那么我们知道 > Promise 状态改变 只有三种

  • 1。 等待态 => 成功态
  • 2。 等待态 => 失败态
  • 3。 等待态 => 等待态 (既不成功也不失败的状态)

所以 调用resolve reject 方法时 要检测当前 Promise 的状态 是等待态 PENDING 就会往下执行 然后改变相应的状态

class Promise {
    constructor(executor){
        this.status = PENDING;
        let resolve = ()=>{
            if(this.status === PENDING){
                this.status = RESOLVE;
            }
        };
        let reject = ()=>{
            if(this.status === PENDING){
                this.status = REJECT;
            }
        };
        executor(resolve, reject);
    }
}

判断完状态后我们需要把相应状态下的结果拿到,就是(1-1-1)例子中 resolve('成功啦,开心') 方法调用传入的为结果;那么我们可以把 成功结果定义为 val_1,失败结果定义为 val_2

class Promise {
    constructor(executor){
        this.status = PENDING;
        this.val_1 = null;
        this.val_2 = null;
        let resolve = (val)=>{
            if(this.status === PENDING){
                this.status = RESOLVE;
                this.val_1 = val;
            }
        };
        let reject = (val)=>{
            if(this.status === PENDING){
                this.status = REJECT;
                this.val_2 = val;
            }
        };
        executor(resolve, reject);
    }
}

写到这里了,我们得想办法把各个状态下的结果拿到,这个时候就需要 then 方法了,这里注意 then 方法是原型的上的方法需要 new Promise().then((ret)=>{},(err)=>{}) 形式调用那么我实现一下 then 方法;

首先我们知道 then 方法有两个参数一个成功回掉一个失败回掉那么我们根据 Promise 的状态进行处理

当状态 为 RESOLVE 那么就调用 successFn 成功方法 同时将成功结果传进去;

反之状态 为 REJECT 那么就调用 errorFn 失败方法 同时将失败结果传进去;

class Promise {
    constructor(executor){
        this.status = PENDING;
        this.val_1 = null;
        this.val_2 = null;
        let resolve = (val)=>{
            if(this.status === PENDING){
                this.status = RESOLVE;
                this.val_1 = val;
            }
        };
        let reject = (val)=>{
            if(this.status === PENDING){
                this.status = REJECT;
                this.val_2 = val;
            }
        };
        executor(resolve, reject);
    }
    
    /**
     * then
     * @param successFn 成功回掉
     * @param errorFn 失败回掉
     */
    then(successFn,errorFn){
        if(this.status === RESOLVE){
            successFn(this.val_1);
        }
        if(this.status === REJECT){
            errorFn(this.val_2);
        }
    }
}

到为止 我们就实现了一个简版的 Promise 我们验证一下哈

    new Promise((resolve, reject)=>{
        resolve('成功了,就开心')
    }).then((ret)=>{
        console.log(ret) // 成功了,就开心
    },(err)=>{
        console.log(err)
    });

    new Promise((resolve, reject)=>{
        reject('失败了,就懊恼')
    }).then((ret)=>{
        console.log(ret)
    },(err)=>{
        console.log(err) // 失败了,就懊恼
    });

表述不正确的地方欢迎同学们 指教指正 --- 一个在前端路上奔跑的小白