使用回调函数实现Promise

内容介绍

原版promise功能介绍和使用请点这里
目前已经实现的方法:

  • myPromiseObj.then()
  • myPromiseObj.catch()
  • myPromiseObj.finally()
  • MyPromise.resolve()
  • MyPromise.reject()
  • MyPromise.race()
  • MyPromise.all()
  • MyPromise.allSettled()

我的目的在于实现promise控制异步任务的功能,而有些不重要(我觉得)的细节可能与原版promise有所不同,比如对与下面这段代码,原生promise输出顺序是===x —x hhh 而mypromise里输出顺序是 ===x hhh --x 。

const resPromise = function(x){
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('===x')
            resolve(x)
            console.log('---x')
        }, 1000)
    })
}
resPromise('hhh').then(val => {console.log(val)})

我想原版的promise可能对状态的改变和then、catch、finally中回调函数的执行做了异步化处理,无论resolve是否同步执行,后面的then、catch、finally中的回调函数全部异步执行。而对于我写的mypromise,如果resolve是同步执行的,那么后面的then、catch、finally中的回调函数也会同步执行。

完整代码

MyPromise.js完整代码如下

function MyPromise(resolver){

    const resolved = 'resolved'
    const pending = 'pending'
    const rejected = 'rejected'
    
    let state = pending
    let resultValue
    let resolveTasks = [] //resolve时执行的任务
    let rejectTasks = []  //reject时执行的任务
    let finallyTasks = []
    
    /* 
        调用resolve可能并不会立即改变状态,
        如果value是promise类型,为了使结果值不为promise类型,它会递归得到value的最终值,然后再根据结果改变状态
        如果最终状态是resolved,那么就调用resolveTasks和finallyTasks
        如果最终状态是rejected,则调用reject 
    */
    function resolve(value){
        if(state !== pending){
            return ;
        }
        if(value instanceof MyPromise){
            value.then(
                val => {resolve(val)},
                reason => reject(reason)
            )
        }
        else {
            state = resolved
            resultValue = value
            for(let resolveTask of resolveTasks){
                resolveTask(value)
            }
            for(let finallyTask of finallyTasks){
                finallyTask()
            }
        }
    }

    //无论value是不是promise类型,立即把结果值改为value,状态值改为rejected,并运行rejectTasks里的函数
    function reject(reason){
        if(state !== pending){
            return ;
        }
        state = rejected
        resultValue = reason
        for(let rejectTask of rejectTasks){
            rejectTask(reason)
        }  
        for(let finallyTask of finallyTasks){
            finallyTask()
        }
    }

    //默认的then里面的第一个回调函数,为了实现值穿透的效果
    function defaultHandler(value){
        return value
    }

    // then返回一个promise,当两个回调函数中的某个被调用时,设返回值为retValue,则在该promise内部会执行resolve(retValue)
    this.then = function(resolveFunction, rejectFunction){
        
        //为了实现值穿透,then中的第一个回调函数为空时,将其赋为此默认值
        resolveFunction = resolveFunction || defaultHandler


        //立即调用then的第一个回调函数,如果没有,则使用默认函数代替,以实现值穿透的效果
        if(state === resolved){
            return new MyPromise((resolve, reject) => {
                resolve(resolveFunction(resultValue))
            })
        }
        //立即调用then的第二个回调函数
        else if(state === rejected){
            return new MyPromise((resolve, reject) => {
                if(rejectFunction instanceof Function){
                    resolve(rejectFunction(resultValue))
                }
                else{
                    //如果缺少错误处理函数,那么直接调用reject
                    //使then()的返回值为 状态=rejected resultValue=本对象结果值 的promise对象,以实现错误穿透效果。
                    reject(resultValue)
                }
            })
        }
        else{
            return new MyPromise((resolve, reject) => {
                function resolveTask(value){
                    resolve(resolveFunction(value))
                }
                function rejectTask(reason){
                    if(rejectFunction instanceof Function){
                        resolve(rejectFunction(resultValue))
                    }
                    else{
                        //原理同上
                        reject(resultValue)
                    }
                }
                resolveTasks.push(resolveTask)
                rejectTasks.push(rejectTask)
            })
        }
    }
    this.catch = function(rejectFunction){
        if(state === rejected){
            return new MyPromise((resolve, reject) => {
                if(rejectFunction instanceof Function){
                    resolve(rejectFunction(resultValue))
                }
                else{
                    //原理同上
                    reject(resultValue)
                }
            })
        }
        else{
            return new MyPromise((resolve, reject) => {
                function rejectTask(reason){
                    if(rejectFunction instanceof Function){
                        resolve(rejectFunction(resultValue))
                    }
                    else{
                        //原理同上
                        reject(resultValue)
                    }
                }
                rejectTasks.push(rejectTask)
            })
            
        }
    }
    this.finally = function(finallyFunction){
        if(!(finallyFunction instanceof Function)){
            return
        }
        if(state !== pending){
            finallyFunction()
        }
        else {
            finallyTasks.push(finallyFunction)
        }
    }
    
    if(!(resolver instanceof Function)){
        throw('param of MyPromise constructor should be a function!')
    }
    else{
       resolver(resolve, reject) 
    }
}

MyPromise.resolve = function(value){
    if(value instanceof MyPromise){
        return value
    }
    return new MyPromise((resolve, reject) => {
        resolve(value)
    })
}
MyPromise.reject = function(value){
    return new MyPromise((resolve, reject) => {
        reject(value)
    })
}

MyPromise.all = function(promises){
    return new MyPromise((resolve, reject) => {
        if(!(promises instanceof Array)){
            throw('param of MyPromis.all() show be an array!')
        }
        let ans = []
        let count = 0
        promises.forEach((promise, index) => {
            if(!(promise instanceof MyPromise)){
                promise = MyPromise.resolve(promise)
            }
            promise.then(
                value => {
                    ans[index] = value
                    count++
                    if(count === promises.length){
                        resolve(ans)
                    }
                },
                reason => {reject(reason)}
            )
        })
    })

}
MyPromise.allSettled = function(promises){
    return new MyPromise((resolve, reject) => {
        if(!(promises instanceof Array)){
            throw('param of MyPromis.allSettled() show be an array!')
        }
        let ans = []
        let count = 0
        promises.forEach((promise, index) => {
            if(!(promise instanceof MyPromise)){
                promise = MyPromise.resolve(promise)
            }
            promise.then(
                value => {
                    let result = {value, status:'fullfilled'}
                    ans[index] = result
                    count++
                    if(count === promises.length){
                        resolve(ans)
                    }
                },
                reason => {
                    let result = {reason, status:'rejected'}
                    ans[index] = result
                    count++
                    if(count === promises.length){
                        resolve(ans)
                    }
                }
            )
        })
    })
}
MyPromise.race = function(promises){
    return new MyPromise((resolve, reject) => {
        if(!(promises instanceof Array)){
            throw('param of MyPromis.race() show be an array!')
        }
        promises.forEach((promise) => {
            if(!(promise instanceof MyPromise)){
                promise = MyPromise.resolve(promise)
            }
            promise.then(
                value => {resolve(value)},
                reason => {reject(reason)}
            )
        })
    })
}
module.exports =  MyPromise
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值