使用回调函数实现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

猜你喜欢

转载自blog.csdn.net/m0_52744273/article/details/127374341