Implementing Promises with Callbacks

Introduction

For the introduction and use of the original promise function, please click here.
The methods that have been implemented so far:

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

My purpose is to realize the function of promise to control asynchronous tasks, and some unimportant (I think) details may be different from the original promise, such as the following code, the output order of the original promise is ===x —x hhh And the output order in mypromise is ===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)})

I think the original promise may asynchronously process the state change and the execution of the callback functions in then, catch, and finally. Regardless of whether resolve is executed synchronously, the subsequent callback functions in then, catch, and finally are all executed asynchronously. As for the mypromise I wrote, if resolve is executed synchronously, then the callback functions in then, catch, and finally will also be executed synchronously.

full code

The complete code of MyPromise.js is as follows

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

Guess you like

Origin blog.csdn.net/m0_52744273/article/details/127374341