手写Promise源码

由于想要更深刻学习promise,翻看了es6官方文档和一些人关于手写promise的一些博客,通过自己的理解手写了promise的一部分功能的源码,加深了自己对promise的理解

目录

1、基本用法

2、基本功能源码

3、then函数源码

4、then函数的链式调用

5、实现then的链式调用的源码

6、promise的状态影响

7、promise状态影响源码

8、完整源码


1、基本用法

构造函数Promise的参数是一个函数,并且该函数有两个参数res和rej分别是Promise内置的函数,当生成一个Promise实例的时候,Promise的内置函数会立即执行,当函数中调用res和rej函数会改变当前promise的状态

let p1=new Promise((res,rej)=>{
  if (Math.random()>0.5)){
    resolve("成功");
  } else {
    reject("失败");
  }
})
p1.then(res=>{                                      
    console.log(res)  //当随机数大于0.5输出成功
},rej=>{
    console.log(rej) //当随机数小于0.5 输出失败
})

2、基本功能源码

***注意调用resolve或reject并不会终结 Promise 的参数函数的执行。

function MyPromise(fn){
    //首先需要将该构造函数传的参数(函数)立即执行,resolve,reject则是其中定义的函数
    try{
        fn(resolve,reject);
    }catch (e) {
        reject(e)
    }
    let self=this;
    //定义当前对象的状态
    this.state="pending";
    this.data="";
    //异步会调的函数集合
    this.resArr=[];
    this.rejArr=[];
    //执行成功的函数,用于将其状态改为成功
    function resolve(data){
        //执行resolve时的状态必须是pending,才可被修改为成功
            if(self.state === 'pending'){
                self.state="resolve"
                self.data=data;
        //当new Promise实例时的内置函数是个异步操作的时候,不会立即改变他的状态,所以先将then定义的函数保存下来,状态改变后再触发
        //let op=new MyPromise((res,rej)=>{
            // setTimeout(function () {
            //    res("34354")
            // },0)
        //})
                while (fn=self.resArr.shift()) {
                    // console.log(fn)
                    fn(data);
                }
            }
    }
     //执行失败的函数,用于将其状态改为失败
    function reject(data){
        //执行reject时的状态必须是pending,才可被修改为失败
            if(self.state === 'pending') {
                self.state='reject';
                self.data=data;
                //同上
                while (fn=self.rejArr.shift()) {
                    // console.log(fn)
                    fn(data);
                }
            }
    }

}

3、then函数源码

当修改完Promise实例的状态后,需要定义一个回调函数去处理成功或者失败的后续操作,then函数是定义在Promise的原型上

MyPromise.prototype.then=function(res,rej){
    let self = this
    if(self.state==='resolve') {
        //函数变为异步操作
        setTimeout(function (){
            res(self.data)
        },0)
    }else if(self.state==='reject') {
        //函数变为异步操作
        setTimeout(function (){
            rej(self.data)
        },0)
    }else if(self.state==="pending"){
        //当new Promise实例时的内置函数是个异步操作的时候,不会立即改变他的状态,所以先将then定义的函数保存下来,状态改变后再触发
        //let op=new MyPromise((res,rej)=>{
            // setTimeout(function () {
            //    res("34354")
            // },0)
        //})
            self.resArr.push(function(res){
                return function(){
                    res(self.data)
                }
            }(res))
        self.rejArr.push(function(rej){
            return function(){
                setTimeout(function (){
                    rej(self.data)
                },0)
            }
        }(rej)) ;

    }
}

4、then函数的链式调用

由于then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。

前提是在then方法中用return返回

op.then(res=>{
    return new MyPromise((res,rej)=>{
       res("222promise")
     })
    }, rej=>{
    return "sss"
    }
).then(res=>{
    console.log(res) //如果是成功状态则打印222promise
},rej=>{
    console.log(rej)//如果是失败状态则打印sss
})

5、实现then的链式调用的源码

MyPromise.prototype.then=function(res,rej){
    let self = this
    //定义一个promise2实例最后return出去,通过判断上一个then的参数(函数)执行的的结果
    //去判断如何触发promise2的resolve函数还是reject函数,实现链式操作
    var promise2=new MyPromise((res2,rej2)=>{
        if(self.state==='resolve') {
            setTimeout(function (){
                let returnValue=res(self.data)
                //判断return出来的数据,实现不同逻辑
                handleReturn(promise2,returnValue,res2,rej2)
            },0)
        }else if(self.state==='reject') {
            setTimeout(function (){
                let returnValue= rej(self.data)
                //判断return出来的数据,实现不同逻辑
                handleReturn(promise2,returnValue,res2,rej2)

            },0)
        }else if(self.state==="pending"){
                self.resArr.push(function(res){
                    return function(){
                        let returnValue=res(self.data)
                        //判断return出来的数据,实现不同逻辑
                        handleReturn(promise2,returnValue,res2,rej2)
                    }
                }(res))
            self.rejArr.push(function(rej){
                return function(){
                    setTimeout(function (){
                        let returnValue= rej(self.data)
                        //判断return出来的数据,实现不同逻辑
                        handleReturn(promise2,returnValue,res2,rej2)
                    },0)
                }
            }(rej)) ;

        }
    })

    return promise2
}

//@promise2:then函数最终要return出去的promise实例
//@returnValue:then函数中的参数(函数)执行return出的结果
//@res2,rej2:promise2中用来触发成功或失败的函数
function handleReturn(promise2,returnValue,res2,rej2){
    //判断return出来的数据是否是promise实例,是则先接受成功(失败)返回的结果,再触发下一个链式
    if(returnValue instanceof MyPromise){
        returnValue.then(res=>{
            res2(res)
        },rej=>{
            rej2(rej)
        })
    }else{
        //如果是原始值的话,则原样返回
        res2(returnValue)
    }

}

6、promise的状态影响

resolve函数的参数除了正常的值以外,还可能是另一个 Promise 实例,比如像下面这样。

let op1=new MyPromise((res,rej)=>{
    res("222")
})
let op=new MyPromise((res,rej)=>{
    res(op1)
})
op.then(res=>{
    console.log(res)  //打印222
},rej=>{
})

7、promise状态影响源码

Promise构造函数中改变状态时多加一层判断

function resolve(data){
    //判断resolve参数是否是promise实例,必须先获取到上一个promise实例状态变化后,将数据传给后续操作
    if(data instanceof MyPromise){
        data.then(res=>{
            resolve(res)
        },rej=>{
            reject(rej)
        })
        return
    }
        if(self.state === 'pending'){
            self.state="resolve"
            self.data=data;
            // console.log(self.resArr)
            while (fn=self.resArr.shift()) {
                // console.log(fn)
                fn(data);
            }
        }
}

8、完整源码

function MyPromise(fn){
    let self=this;
    //定义当前对象的状态
    this.state="pending";
    this.data="";
    //异步会调的函数集合
    this.resArr=[];
    this.rejArr=[];
    //执行成功的函数,用于将其状态改为成功
    function resolve(data){
        if(data instanceof MyPromise){
            data.then(res=>{
                resolve(res)
            },rej=>{
                reject(rej)
            })
            return
        }
        //执行resolve时的状态必须是pending,才可被修改为成功
            if(self.state === 'pending'){
                self.state="resolve"
                self.data=data;
              //当new Promise实例时的内置函数是个异步操作的时候,不会立即改变他的状态,所以先将then定义的函数保存下来,状态改变后再触发
        //let op=new MyPromise((res,rej)=>{
            // setTimeout(function () {
            //    res("34354")
            // },0)
        //})
                while (fn=self.resArr.shift()) {
                    // console.log(fn)
                    fn(data);
                }
            }
    }
     //执行失败的函数,用于将其状态改为失败
    function reject(data){
            if(self.state === 'pending') {
                self.state='reject';
                self.data=data;
                while (fn=self.rejArr.shift()) {
                    // console.log(fn)
                    fn(data);
                }
            }
    }
     //首先需要将该构造函数传的参数(函数)立即执行,resolve,reject则是其中定义的函数
    try{
        fn(resolve,reject);
    }catch (e) {
        reject(e)
    }

}
 //判断return出来的数据,实现不同逻辑
//@promise2:then函数最终要return出去的promise实例
//@returnValue:then函数中的参数(函数)执行return出的结果
//@res2,rej2:promise2中用来触发成功或失败的函数
function handleReturn(promise2,returnValue,res2,rej2){
    //判断return出来的数据是否是promise实例,是则先接受成功(失败)返回的结果,再触发下一个链式
    if(returnValue instanceof MyPromise){
        returnValue.then(res=>{
            res2(res)
        },rej=>{
            rej2(rej)
        })
    }else{
        res2(returnValue)
    }
}
MyPromise.prototype.then=function(res,rej){
    let self = this
    //定义一个promise2实例最后return出去,通过判断上一个then的参数(函数)执行的的结果
    //去判断如何触发promise2的resolve函数还是reject函数,实现链式操作
    var promise2=new MyPromise((res2,rej2)=>{
        if(self.state==='resolve') {
        //函数变为异步操作
            setTimeout(function (){
                let returnValue=res(self.data)
                handleReturn(promise2,returnValue,res2,rej2)
            },0)
        }else if(self.state==='reject') {
        //函数变为异步操作
            setTimeout(function (){
                let returnValue= rej(self.data)
                handleReturn(promise2,returnValue,res2,rej2)

            },0)
        }else if(self.state==="pending"){
        //当new Promise实例时的内置函数是个异步操作的时候,不会立即改变他的状态,所以先将then定义的函数保存下来,状态改变后再触发
        //let op=new MyPromise((res,rej)=>{
            // setTimeout(function () {
            //    res("34354")
            // },0)
        //})
                self.resArr.push(function(res){
                    return function(){
                        let returnValue=res(self.data)
                        handleReturn(promise2,returnValue,res2,rej2)
                    }
                }(res))
            self.rejArr.push(function(rej){
                return function(){
                    setTimeout(function (){
                        let returnValue= rej(self.data)
                        handleReturn(promise2,returnValue,res2,rej2)
                    },0)
                }
            }(rej)) ;

        }
    })

    return promise2
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值