手撕Promise

有两种方法,一种是用函数原型链,另一种是用es6提供的class。不过class的本质就是函数原型链。

1. 函数原型链方式

先创建构造函数Promise

function Promise(exe){
    this.PromiseState = 'pending' 
    this.PromiseResult = null
    this.callbacks = []   //作用是当《异步调用》时,保存then中的方法。 用数组是因为多个then调用时 用数组储存起来,后续foreach遍历。 
    let self = this    //保存一下this
    function resolve(value){
        if(self.PromiseState !== 'pending') return   //控制Promise只能由pending到fulfilled
        self.PromiseResult = value    //改变结果
        self.PromiseState = 'fulfilled'       //改变状态
        setTimeout(() => {
            self.callbacks.forEach(item => item.onresolved())  //把所有的then方法全部执行            
        });
    }

    function reject(reason){
        if(self.PromiseState !== 'pending') return   //控制Promise只能由pending到reject
        self.PromiseResult = reason   //改变结果
        self.PromiseState = 'rejected'    //改变状态
        setTimeout(() => {
            self.callbacks.forEach(item => item.onrejected())   //把所有的then方法全部执行
        });
    }
    try{   
        exe(resolve,reject)   //立刻同步调用执行
    }catch(e){
        reject(e)
    }

}

创建完构造函数之后,最关键的then方法,它能处理后续内容,并且返回一个promise对象

Promise.prototype.then = function(onresolved,onrejected){
    let self = this
    return new Promise((resolve,reject)=>{   //.then返回的是Promise对象( let p2 = p.then(fun) )
        //用callback函数封装处理then()过程
        function callback(type){   //用来处理返回promise对象的状态,如果返回promise对象,则子promise的状态和结果 = 父promise,如果是常量就改变父promise结果
            try{
                let result = type(self.PromiseResult)   //result是then函数体执行后的结果(即return的东西) 他是一个常量或者Promise对象
                if(result instanceof Promise){   //如果return的是promise对象,调用result的then来控制父对象 resolve父成功 reject失败
                    result.then(v =>{resolve(v)},r =>{reject(r)})   //result对象的then可以知道成功还是失败  调用result的then方法只是为了利用成功和失败回调来判断父Promise是成功还是失败
                }else{   //如果是常量,直接resolve改变状态
                    resolve(result)
                }
            }catch(e){    //当throw的时候直接把promise状态改为失败,并把错误信息交给then promise 对象结果
                reject(e)
            }
        }

        if(typeof onresolved !== 'function'){   //如果用户没有在then中传函数类型的参数,则默认返回resolve()中的结果
            console.warn('then中第一个参数为回调函数!pjr帮你默认返回结果了')
            onresolved = value => value
        }

        if(typeof onrejected !== 'function'){   //一般都不会写第二个失败的回调,如果有异常直接抛出,一层一层往下找,直到找到有第二个回调的then或者找到catch。
            onrejected = reason => {throw reason}
        }

        if(this.PromiseState == 'fulfilled'){
            setTimeout(() => {
                callback(onresolved)    //同步调用 状态成功 直接在这里处理完毕。
            })
        }
        else if(this.PromiseState == 'rejected'){
            setTimeout(() => {
                callback(onrejected)    //同步调用 状态失败 直接在这里处理完毕。
            })
        }
        else if(this.PromiseState == 'pending'){   //!重点!!!  如果是异步任务,会先进入then,把所有then里的方法保存到实例的callbacks数组里,然后再在resolve或者reject函数里调用callback里的onresolved或者onrejected函数执行
            this.callbacks.push({
                onresolved:() => callback(onresolved),
                onrejected:() => callback(onrejected)
            })
        }
    })
}

then对应有个catch方法,catch方法本质是then的语法糖。并且具有异常穿透

Promise.prototype.catch = function(onrejected){    //catch方法,本质是then的语法糖
    this.then(undefined, onrejected)
}

Promise.resolve()方法,快速得到一个成功的Promise对象,如果return 一个新promise对象,新promise对象的结果就是Promise.resolve()的结果

Promise.resolve = function(value){
    return new Promise((resolve,reject) =>{
        if(value instanceof Promise){
            value.then(v => {resolve(v)},r => {reject(r)})
        }
        else{
            resolve(value)
        }
    })
}

Promise.reject()方法,快速得到一个失败的Promise对象,不管什么情况都是失败的Promise对象

Promise.reject = function(reason){
    return new Promise((resolve,reject) =>{
        reject(reason)
    })
}

Promise.all(promises)方法,传入一个数组(数组名暂定为promises),promises里是几个promise对象。返回结果是一个Promise对象,它的状态由promises每个元素决定,promises里的每个为状态才为真,有一个假状态就是假。返回promise的结果:如果全真,结果是几个promise结果数组;如果有假,结果为假的值。

Promise.all = function(promises){
    let arr = [],count = 0;
    return new Promise((resolve,reject) => {
        for(let i in promises){
            promises[i].then(v => {
                count++
                arr[i] = v
                if(count === promises.length){
                    resolve(arr)
                }
            },r =>{
                reject(r)
            })
        }
    })
}

Promise.race(promises)。类似于Promise.all(),区别是返回结果为第一个完成的promise的结果

Promise.race = function(promises){
    return new Promise((resolve,reject) => {
        for(let i in promises){
            promises[i].then(v => {
                resolve(v)
            },r => {
                reject(r)
            })
        }
    })
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值