很多大厂面试的时候会问到如何实现Promise,出于对Promise内部底层实现原理的探知。自己通过搜集一些资料,从一开始模仿着实现。到最后控制台调试以及逐行代码阅读理解,算是搞清楚了Promise实现原理。

原生Promise

在手写Promise之前肯定要了解原生Promise究竟是怎样使用,然后再一步步模拟实现,首先来个原生Promise的例子:


    new Promise((resolve,reject)=>{
        //模拟异步
        setTimeout(()=>{
            resolve('Promise')
        },1000)
    }).then(res=>{
        console.log(res) //1秒后输出Promise
    },err=>{
        //异常情况
    })

可以根据Promise写法来推断实现原理:

  1. 首先通过new Promise构造函数,生成Promise对象(实例)。Promise构造函数中传入一个函数,传入的函数中包含两个参数,他们分别也是函数。
  2. 在Promise传入的函数内部执行异步代码,异步代码体内执行完成逻辑之后调用resolve函数,最终把异步结果通过resolve传递出去。
  3. 通过new Promise生成的Promise对象会有个then方法,then方法里面也有两个参数,分别代表成功和异常的回调函数(有顺序)。

简易版的Promise


    function _Promise(executor){
        let self = this;
        self.status = 'pending' //初始化Promise状态
        self.value = '' //存储Promise成功/失败回调的值
        self.onResolvedCallBacks = []; //存储Promise resolve成功回调函数集
        self.onRejectedCallBacks = []//存储Promise reject失败回调函数集

        //resolve成功回调
        function resolve(){

        }
        //reject异常回调
        function reject(){

        }

        executor(resolve,reject) //执行传入的回调并传入相应的参数
    }

以上是_Promise构造函数主体,接下来我们就要填充resolve、reject函数,然后再做一些优化


    function _Promise(executor){
        let self = this;
        self.status = 'pending' //初始化Promise状态
        self.value = '' //存储Promise成功/失败回调的值
        self.onResolvedCallBacks = []; //存储Promise resolve成功回调函数集
        self.onRejectedCallBacks = []//存储Promise reject失败回调函数集

        //resolve成功回调
        function resolve(value){
            if(self.status == 'pending'){
                self.status = 'resolved';
                self.value = value;
                for (let i = 0; i < self.onResolvedCallBacks.length; i++) {
                        self.onResolvedCallBacks[i](value);
                }
            }
        }
        //reject异常回调
        function reject(err){
            if(self.status == 'pending'){
                self.status = 'rejected';
                self.value = err;
                for (let i = 0; i < self.onRejectedCallBacks.length; i++) {
                       self.onRejectedCallBacks[i](err);
                }
            }
        }

        //为了考虑执行executor的过程中可能会有异常情况,所以我们就用try和catch包裹起来
        try{
            executor(resolve,reject) //执行传入的回调并传入相应的参数
        }catch(err){
            reject(err)
        }
    }

Promise构造函数内部逻辑基本上就是判断状态为pending之后把状态改为相应的值,然后把resolve和reject对应的参数存在self.value上。之后执行相应的回调。

之后就是then方法的实现,我们把then方法挂到原型上


    _Promise.prototype.then = function(onResolved,onRejected){
        let self = this;

        onResolved = typeof onResolved == 'function' ? onResolved : function(res){}
        onRejected = typeof onRejected == 'function' ? onRejected : function(err){}

        if(self.status == 'pending'){
            self.onResolvedCallBacks.push(onResolved)
            self.onRejectedCallBacks.push(onRejected)
        }

        if(self.status == 'resolved'){
            onResolved(self.value)
        }
        if(self.status == 'rejected'){
            onRejected(self.value)
        }
    }

最后测试下代码:


    new _Promise(resolve=>{
        setTimeout(()=>{
            resolve('hello Promise')
        },2000)
    }).then(res=>{
        console.log('res 的值是:',res); // 2s后执行 res 的值是 'hello Promise'
    })