Javascript - Promise的实现过程

一、认识Promise

Promise是一个类,可以翻译成 承诺、许诺 、期约

当我们需要给予调用者一个承诺:待会儿我会给你回调数据时,就可以创建一个Promise的对象

二、Promise的状态
    待定(pending)
    完成(fulfilled)
    拒绝(rejected)
    一旦状态被确定下来,Promise的状态会被 锁死,该Promise的状态是不可更改的

三、其他promise的API建议自己查询文档,本文只注重功能的实现

四、代码实现步骤:

1、代码结构的简单实现

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected' //状态来保证resolve后的reject是无效调用反之亦然

class MyPromise {
    constructor(executor) {
        this.status = PROMISE_STATUS_PENDING
        this.value = undefined
        this.reason = undefined
        const resolve = (value) => {
            if (this.status === PROMISE_STATUS_PENDING) {
                this.status = PROMISE_STATUS_FULFILLED
                this.value = value
                console.log(this.value, 'resolve被调用了');
            }

        }
        const reject = (reason) => {
            if (this.status === PROMISE_STATUS_PENDING) {
                this.status = PROMISE_STATUS_REJECTED
                this.reason = reason
                console.log(this.reason, 'reject被调用了');
            }

        }
        executor(resolve, reject)
    }

}

//实例化
const promise = new MyPromise((resolve, reject) => {
    console.log('状态pending');
    reject('我是reject')
    resolve('我是resolve')
})

2、then方法设计

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected' //状态来保证resolve后的reject是无效调用反之亦然

class MyPromise {
    constructor(executor) {
        this.status = PROMISE_STATUS_PENDING
        this.value = undefined
        this.reason = undefined
        const resolve = (value) => {
            if (this.status === PROMISE_STATUS_PENDING) {
                this.status = PROMISE_STATUS_FULFILLED
                // this.onFulfilled() // this.onFulfilled is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    this.value = value
                    this.onFulfilled(this.value)
                    console.log(this.value, 'resolve被调用了');
                })

            }

        }
        const reject = (reason) => {
            if (this.status === PROMISE_STATUS_PENDING) {
                this.status = PROMISE_STATUS_REJECTED
                // this.onRejected() // this.onRejected is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    this.reason = reason
                    this.onRejected(this.reason)
                    console.log(this.reason, 'reject被调用了');
                })

            }

        }
        executor(resolve, reject)
    }
    then(onFulfilled, onRejected) {
        this.onFulfilled = onFulfilled
        this.onRejected = onRejected
    }

}

//实例化
const promise = new MyPromise((resolve, reject) => {
    console.log('状态pending');
    resolve('我是resolve')
    reject('我是reject')
})

promise.then(res => {
    console.log(res, 'res');
}, err => {
    console.log(err, 'err');
})

3、then方法优化之-多次调用

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected' //状态来保证resolve后的reject是无效调用反之亦然

class MyPromise {
    constructor(executor) {
        this.status = PROMISE_STATUS_PENDING
        this.value = undefined
        this.reason = undefined
        //多次调用需要用数组来接收
        this.onFulfilledFns = []
        this.onRejectedFns = []

        const resolve = (value) => {
            if (this.status === PROMISE_STATUS_PENDING) {
                this.status = PROMISE_STATUS_FULFILLED
                // this.onFulfilled() // this.onFulfilled is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    this.value = value
                    this.onFulfilledFns.forEach(fn => {
                        fn(this.value)
                    })
                })

            }

        }
        const reject = (reason) => {
            if (this.status === PROMISE_STATUS_PENDING) {
                this.status = PROMISE_STATUS_REJECTED
                // this.onRejected() // this.onRejected is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    this.reason = reason
                    this.onRejectedFns.forEach(fn => {
                        fn(this.reason)
                    })
                })

            }

        }
        executor(resolve, reject)
    }
    then(onFulfilled, onRejected) {
        this.onFulfilledFns.push(onFulfilled)
        this.onRejectedFns.push(onRejected)
    }

}

//实例化
const promise = new MyPromise((resolve, reject) => {
    console.log('状态pending');
    reject('我是reject')
    resolve('我是resolve')
})

//测试多次调用情况,未做处理时后面代码覆盖前面代码
promise.then(res => {
    console.log(res, 'res');
}, err => {
    console.log(err, 'err');
})

promise.then(res2 => {
    console.log(res2, 'res2');
}, res2 => {
    console.log(res2, 'err2');
})

3、then方法优化之-延迟回调的情况

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected' //状态来保证resolve后的reject是无效调用反之亦然

class MyPromise {
    constructor(executor) {
        this.status = PROMISE_STATUS_PENDING
        this.value = undefined
        this.reason = undefined
        //多次调用需要用数组来接收
        this.onFulfilledFns = []
        this.onRejectedFns = []

        const resolve = (value) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onFulfilled() // this.onFulfilled is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_FULFILLED
                    this.value = value
                    this.onFulfilledFns.forEach(fn => {
                        fn(this.value)
                    })
                })

            }

        }
        const reject = (reason) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onRejected() // this.onRejected is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_REJECTED
                    this.reason = reason
                    this.onRejectedFns.forEach(fn => {
                        fn(this.reason)
                    })
                })

            }

        }
        executor(resolve, reject)
    }
    then(onFulfilled, onRejected) {
        // 1.如果在调用then的时候,状态是已经确定的情况
        if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
            onFulfilled(this.value)
        }
        if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
            onRejected(this.reason)
        }

        //2.状态未定的时候,将成功回调和失败的回调放到数组中
        if (this.status === PROMISE_STATUS_PENDING) {
            this.onFulfilledFns.push(onFulfilled)
            this.onRejectedFns.push(onRejected)
        }

    }

}

//实例化
const promise = new MyPromise((resolve, reject) => {
    console.log('状态pending');
    reject('我是reject')
    resolve('我是resolve')
})

//在确定Promise状态之后, 再次调用then,但在有延迟的情况下无法加进去,只能打印'状态pending'
setTimeout(() => {
    promise.then(res => {
        console.log("res3:", res)
    }, err => {
        console.log("err3:", err)
    })
}, 1000)

4、then方法优化之【嵌套】多次调用

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected' //状态来保证resolve后的reject是无效调用反之亦然

class MyPromise {
    constructor(executor) {
        this.status = PROMISE_STATUS_PENDING
        this.value = undefined
        this.reason = undefined
        //多次调用需要用数组来接收
        this.onFulfilledFns = []
        this.onRejectedFns = []

        const resolve = (value) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onFulfilled() // this.onFulfilled is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_FULFILLED
                    this.value = value
                    this.onFulfilledFns.forEach(fn => {
                        fn(this.value)
                    })
                })

            }

        }
        const reject = (reason) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onRejected() // this.onRejected is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_REJECTED
                    this.reason = reason
                    this.onRejectedFns.forEach(fn => {
                        fn(this.reason)
                    })
                })

            }

        }
        executor(resolve, reject)
    }
    then(onFulfilled, onRejected) {
        return new MyPromise((resolve, reject) => {
            // 1.如果在调用then的时候,状态是已经确定的情况
            if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
                // onFulfilled(this.value)
                try {
                    const val = onFulfilled(this.value)
                    resolve(val)
                } catch {

                }
            }
            if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
                // onRejected(this.reason)
                try {
                    const val = onRejected(this.reason)
                    resolve(val)
                } catch {

                }
            }

            //2.状态未定的时候,将成功回调和失败的回调放到数组中
            if (this.status === PROMISE_STATUS_PENDING) {
                // this.onFulfilledFns.push(onFulfilled)
                // this.onRejectedFns.push(onRejected)
                this.onFulfilledFns.push(() => {
                    try {
                        const val = onFulfilled(this.value)
                        resolve(val)
                    } catch {

                    }
                })
                this.onRejectedFns.push(() => {
                    try {
                        const val = onRejected(this.reason) 
                        resolve(val) //强调://这个地方也是resolve,只有throw error才会进入下一个reject
                    } catch {

                    }
                })
            }
        })


    }

}

//实例化
const promise = new MyPromise((resolve, reject) => {
    console.log('状态pending');
    resolve('我是resolve')
    reject('我是reject')
})

//then的返回值默认为undefined,如果有具体的返回值也是会转成promise对象,返回值可以继续通过下一个then/catch来接收
//如何实现的:
// 在then方法中return一个promise,将结果resolve出去
promise.then(res => {
    console.log("res1:", res)
    return "我可以继续往下传下去"
}, err => {
    console.log("err1:", err)
    return "依旧可以传下去"
}).then(res => {
    console.log("res2:", res)
}, err => {
    console.log("err2:", err)
})

5、处理promise或者then中抛错的问题

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected' //状态来保证resolve后的reject是无效调用反之亦然

class MyPromise {
    constructor(executor) {
        this.status = PROMISE_STATUS_PENDING
        this.value = undefined
        this.reason = undefined
        //多次调用需要用数组来接收
        this.onFulfilledFns = []
        this.onRejectedFns = []

        const resolve = (value) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onFulfilled() // this.onFulfilled is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_FULFILLED
                    this.value = value
                    this.onFulfilledFns.forEach(fn => {
                        fn(this.value)
                    })
                })

            }

        }
        const reject = (reason) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onRejected() // this.onRejected is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_REJECTED
                    this.reason = reason
                    this.onRejectedFns.forEach(fn => {
                        fn(this.reason)
                    })
                })

            }

        }
        //抛错处理一:
        try {
            executor(resolve, reject)
        } catch (err) {
            reject(err) // 这里可以捕获promise抛错
        }
    }
     //抛错处理二:
    then(onFulfilled, onRejected) {
        return new MyPromise((resolve, reject) => {
            // 1.如果在调用then的时候,状态是已经确定的情况
            if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
                // onFulfilled(this.value)
                try {
                    const val = onFulfilled(this.value)
                    resolve(val)
                } catch (err) {
                    reject(err)
                }
            }
            if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
                // onRejected(this.reason)
                try {
                    const val = onRejected(this.reason)
                    resolve(val)
                } catch (err) {
                    reject(err)
                }
            }

            //2.状态未定的时候,将成功回调和失败的回调放到数组中
            if (this.status === PROMISE_STATUS_PENDING) {
                // this.onFulfilledFns.push(onFulfilled)
                // this.onRejectedFns.push(onRejected)
                this.onFulfilledFns.push(() => {
                    try {
                        const val = onFulfilled(this.value)
                        resolve(val)
                    } catch(err) {
                        reject(err)
                    }
                })
                this.onRejectedFns.push(() => {
                    try {
                        const val = onRejected(this.reason) 
                        resolve(val) //强调://这个地方也是resolve,只有throw error才会进入下一个reject
                    } catch (err) {
                        reject(err)
                    }
                })
            }
        })


    }

}

//实例化
const promise = new MyPromise((resolve, reject) => {
    console.log('状态pending');
    throw new Error("promise中抛错") //promise中抛错
    reject('我是reject')
    resolve('我是resolve')
})


promise.then(res => {
    console.log("res1:", res)
    // throw new Error("then抛错") //then抛错
    return "我可以继续往下传下去"
}, err => {
    console.log("err1:", err)
    // throw new Error("then抛错") //then抛错
    return "依旧可以传下去"
}).then(res => {
    console.log("res2:", res)
}, err => {
    console.log("err2:", err)
})

6、try..catch代码过于冗余,抽取公共方法来优化

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected' //状态来保证resolve后的reject是无效调用反之亦然
//抽取工具函数
function commonFunc(execFn, value, resolve, reject) {
    try {
        const result = execFn(value)
        resolve(result)
    } catch (err) {
        reject(err)
    }
}
class MyPromise {
    constructor(executor) {
        this.status = PROMISE_STATUS_PENDING
        this.value = undefined
        this.reason = undefined
        //多次调用需要用数组来接收
        this.onFulfilledFns = []
        this.onRejectedFns = []

        const resolve = (value) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onFulfilled() // this.onFulfilled is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_FULFILLED
                    this.value = value
                    this.onFulfilledFns.forEach(fn => {
                        fn(this.value)
                    })
                })

            }

        }
        const reject = (reason) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onRejected() // this.onRejected is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_REJECTED
                    this.reason = reason
                    this.onRejectedFns.forEach(fn => {
                        fn(this.reason)
                    })
                })

            }

        }
        //抛错处理一:
        try {
            executor(resolve, reject)
        } catch (err) {
            reject(err) // 这里可以捕获promise抛错
        }
    }
    //抛错处理二:
    then(onFulfilled, onRejected) {
        return new MyPromise((resolve, reject) => {
            // 1.如果在调用then的时候,状态是已经确定的情况
            if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
                // onFulfilled(this.value)
                // try {
                //     const val = onFulfilled(this.value)
                //     resolve(val)
                // } catch (err) {
                //     reject(err)
                // }
                commonFunc(onFulfilled, this.value, resolve, reject)
            }
            if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
                // onRejected(this.reason)
                // try {
                //     const val = onRejected(this.reason)
                //     resolve(val)
                // } catch (err) {
                //     reject(err)
                // }
                commonFunc(onRejected, this.reason, resolve, reject)
            }

            //2.状态未定的时候,将成功回调和失败的回调放到数组中
            if (this.status === PROMISE_STATUS_PENDING) {
                // this.onFulfilledFns.push(onFulfilled)
                // this.onRejectedFns.push(onRejected)
                this.onFulfilledFns.push(() => {
                    // try {
                    //     const val = onFulfilled(this.value)
                    //     resolve(val)
                    // } catch (err) {
                    //     reject(err)
                    // }
                    commonFunc(onFulfilled, this.value, resolve, reject)
                })
                this.onRejectedFns.push(() => {
                    // try {
                    //     const val = onRejected(this.reason)
                    //     resolve(val) //强调://这个地方也是resolve,只有throw error才会进入下一个reject
                    // } catch (err) {
                    //     reject(err)
                    // }
                    commonFunc(onRejected, this.reason, resolve, reject)
                })
            }
        })


    }

}

//实例化
const promise = new MyPromise((resolve, reject) => {
    console.log('状态pending');
    // throw new Error("promise中抛错") //promise中抛错
    reject('我是reject')
    resolve('我是resolve')
})


promise.then(res => {
    console.log("res1:", res)
    throw new Error("then抛错") //then抛错
    return "我可以继续往下传下去"
}, err => {
    console.log("err1:", err)
    throw new Error("then抛错") //then抛错
    return "依旧可以传下去"
}).then(res => {
    console.log("res2:", res)
}, err => {
    console.log("err2:", err)
})

7、实现catch方法

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected' //状态来保证resolve后的reject是无效调用反之亦然
//抽取工具函数
function commonFunc(execFn, value, resolve, reject) {
    try {
        const result = execFn(value)
        resolve(result)
    } catch (err) {
        reject(err)
    }
}
class MyPromise {
    constructor(executor) {
        this.status = PROMISE_STATUS_PENDING
        this.value = undefined
        this.reason = undefined
        //多次调用需要用数组来接收
        this.onFulfilledFns = []
        this.onRejectedFns = []

        const resolve = (value) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onFulfilled() // this.onFulfilled is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_FULFILLED
                    this.value = value
                    this.onFulfilledFns.forEach(fn => {
                        fn(this.value)
                    })
                })

            }

        }
        const reject = (reason) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onRejected() // this.onRejected is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_REJECTED
                    this.reason = reason
                    this.onRejectedFns.forEach(fn => {
                        fn(this.reason)
                    })
                })

            }

        }
        //抛错处理一:
        try {
            executor(resolve, reject)
        } catch (err) {
            reject(err) // 这里可以捕获promise抛错
        }
    }
    //抛错处理二:
    then(onFulfilled, onRejected) {
        //新增catch方法的时候这里要新增几个优化点 - 不做处理会报 execFn is not a function
        console.log(onRejected); // undefined 为什么undefined看最下面的解释
        const defaultOnRejected = err => {throw err }
        onRejected = onRejected || defaultOnRejected


        
        return new MyPromise((resolve, reject) => {
            // 1.如果在调用then的时候,状态是已经确定的情况
            if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
                // onFulfilled(this.value)
                // try {
                //     const val = onFulfilled(this.value)
                //     resolve(val)
                // } catch (err) {
                //     reject(err)
                // }
                commonFunc(onFulfilled, this.value, resolve, reject)
            }
            if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
                // onRejected(this.reason)
                // try {
                //     const val = onRejected(this.reason)
                //     resolve(val)
                // } catch (err) {
                //     reject(err)
                // }
                commonFunc(onRejected, this.reason, resolve, reject)
            }

            //2.状态未定的时候,将成功回调和失败的回调放到数组中
            if (this.status === PROMISE_STATUS_PENDING) {
                // this.onFulfilledFns.push(onFulfilled)
                // this.onRejectedFns.push(onRejected)
                this.onFulfilledFns.push(() => {
                    // try {
                    //     const val = onFulfilled(this.value)
                    //     resolve(val)
                    // } catch (err) {
                    //     reject(err)
                    // }
                    commonFunc(onFulfilled, this.value, resolve, reject)
                })
                this.onRejectedFns.push(() => {
                    // try {
                    //     const val = onRejected(this.reason)
                    //     resolve(val) //强调://这个地方也是resolve,只有throw error才会进入下一个reject
                    // } catch (err) {
                    //     reject(err)
                    // }
                    commonFunc(onRejected, this.reason, resolve, reject)
                })
            }
        })


    }

    catch(onRejected) {
        this.then(undefined,onRejected)
    }

}

//实例化
const promise = new MyPromise((resolve, reject) => {
    console.log('状态pending');
    // throw new Error("promise中抛错") //promise中抛错
    reject('我是reject')
    resolve('我是resolve')
})


// promise.then(res => {
//     console.log("res:", res)
// },err => {
    
// }).catch(err => {
//   上面err返回的结果
// })

promise.then(res => {
    console.log("res:", res)
}).catch(err => {
    console.log("err:", err)
    //注意:这个catch是拿不到reject返回出来的值的,他能拿到的是上面的promise的err所返回出来的undefined,他是一个新的promise 相当于new MyPromise.catch()
    // 解决:让上面的promise返回出来这个err,catch就能捕获了
    // promise1: err => {
    //     throw err
    // }
    // promise2: err => {
    // }
})

8、实现finally方法

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected' //状态来保证resolve后的reject是无效调用反之亦然
//抽取工具函数
function commonFunc(execFn, value, resolve, reject) {
    try {
        const result = execFn(value)
        resolve(result)
    } catch (err) {
        reject(err)
    }
}
class MyPromise {
    constructor(executor) {
        this.status = PROMISE_STATUS_PENDING
        this.value = undefined
        this.reason = undefined
        //多次调用需要用数组来接收
        this.onFulfilledFns = []
        this.onRejectedFns = []

        const resolve = (value) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onFulfilled() // this.onFulfilled is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_FULFILLED
                    this.value = value
                    this.onFulfilledFns.forEach(fn => {
                        fn(this.value)
                    })
                })

            }

        }
        const reject = (reason) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onRejected() // this.onRejected is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_REJECTED
                    this.reason = reason
                    this.onRejectedFns.forEach(fn => {
                        fn(this.reason)
                    })
                })

            }

        }
        //抛错处理一:
        try {
            executor(resolve, reject)
        } catch (err) {
            reject(err) // 这里可以捕获promise抛错
        }
    }
    //抛错处理二:
    then(onFulfilled, onRejected) {
        //新增catch方法的时候这里要新增几个优化点 - 不做处理会报 execFn is not a function
        // console.log(onRejected); // undefined 为什么undefined看最下面的解释
        const defaultOnRejected = err => {
            throw err
        }
        onRejected = onRejected || defaultOnRejected

        const defaultOnFulfilled = value => {
            return value
        }
        onFulfilled = onFulfilled || defaultOnFulfilled

        return new MyPromise((resolve, reject) => {
            // 1.如果在调用then的时候,状态是已经确定的情况
            if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
                commonFunc(onFulfilled, this.value, resolve, reject)
            }
            if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
                commonFunc(onRejected, this.reason, resolve, reject)
            }

            //2.状态未定的时候,将成功回调和失败的回调放到数组中
            if (this.status === PROMISE_STATUS_PENDING) {
                if (onFulfilled)  this.onFulfilledFns.push(() => {
                    commonFunc(onFulfilled, this.value, resolve, reject)
                })
                if (onRejected) this.onRejectedFns.push(() => {
                    commonFunc(onRejected, this.reason, resolve, reject)
                })
            }
        })


    }

    catch (onRejected) {
       return this.then(undefined, onRejected)
    }
    
    finally(onFinally) {
        this.then(() => {
            onFinally()
        }, () => {
            onFinally()
        })
    }

}

//实例化
const promise = new MyPromise((resolve, reject) => {
    console.log('状态pending');
    // throw new Error("promise中抛错") //promise中抛错
    resolve('我是resolve')
    reject('我是reject')
})

// 测试一下:
// promise.then(res => {
// }).finally(() => {
//     console.log("finally") //finally 
// })

//多次调用情况下的finally
promise.then(res => {
    console.log("res1:", res)
    return '陈非凡'
}, err => {
    console.log("err1:", err)
}).then(res2 => {
    console.log("res2:", res2)
}).catch(err3 => {
    console.log('err3', err3);
}).finally(() => {
    console.log('finally');
    //Cannot read property 'finally' of undefined 直接这样写会报错原因:需要catch也返回一个promise,在catch方法中 return this.then(undefined, onRejected) 即可
    // 注意:catch会阻碍finally打印的情况 onFulfilled = onFulfilled || defaultOnFulfilled 因为resolve的时候的then没有继续处理,没有传到下一步 所以finally没有执行
})

9、实现resolve和reject方法

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected' //状态来保证resolve后的reject是无效调用反之亦然
//抽取工具函数
function commonFunc(execFn, value, resolve, reject) {
    try {
        const result = execFn(value)
        resolve(result)
    } catch (err) {
        reject(err)
    }
}
class MyPromise {
    constructor(executor) {
        this.status = PROMISE_STATUS_PENDING
        this.value = undefined
        this.reason = undefined
        //多次调用需要用数组来接收
        this.onFulfilledFns = []
        this.onRejectedFns = []

        const resolve = (value) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onFulfilled() // this.onFulfilled is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_FULFILLED
                    this.value = value
                    this.onFulfilledFns.forEach(fn => {
                        fn(this.value)
                    })
                })

            }

        }
        const reject = (reason) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onRejected() // this.onRejected is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_REJECTED
                    this.reason = reason
                    this.onRejectedFns.forEach(fn => {
                        fn(this.reason)
                    })
                })

            }

        }
        //抛错处理一:
        try {
            executor(resolve, reject)
        } catch (err) {
            reject(err) // 这里可以捕获promise抛错
        }
    }
    //抛错处理二:
    then(onFulfilled, onRejected) {
        //新增catch方法的时候这里要新增几个优化点 - 不做处理会报 execFn is not a function
        // console.log(onRejected); // undefined 为什么undefined看最下面的解释
        const defaultOnRejected = err => {
            throw err
        }
        onRejected = onRejected || defaultOnRejected

        const defaultOnFulfilled = value => {
            return value
        }
        onFulfilled = onFulfilled || defaultOnFulfilled

        return new MyPromise((resolve, reject) => {
            // 1.如果在调用then的时候,状态是已经确定的情况
            if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
                commonFunc(onFulfilled, this.value, resolve, reject)
            }
            if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
                commonFunc(onRejected, this.reason, resolve, reject)
            }

            //2.状态未定的时候,将成功回调和失败的回调放到数组中
            if (this.status === PROMISE_STATUS_PENDING) {
                if (onFulfilled)  this.onFulfilledFns.push(() => {
                    commonFunc(onFulfilled, this.value, resolve, reject)
                })
                if (onRejected) this.onRejectedFns.push(() => {
                    commonFunc(onRejected, this.reason, resolve, reject)
                })
            }
        })


    }

    catch (onRejected) {
       return this.then(undefined, onRejected)
    }
    
    finally(onFinally) {
        this.then(() => {
            onFinally()
        }, () => {
            onFinally()
        })
    }

    static resolve(value) {
        return new MyPromise((resolve) => {
            resolve(value)
        })
    }

    static reject(reason) {
        return new MyPromise((resolve,reject) => {
            reject(reason)
        })
    }

}

//实例化
const promise = new MyPromise((resolve, reject) => {
    console.log('状态pending');
    // throw new Error("promise中抛错") //promise中抛错
    resolve('我是resolve')
    reject('我是reject')
})


MyPromise.resolve('你好陈非凡').then(res => {
    console.log(res);
})

MyPromise.reject('哎呀报错了').catch(err => {
    console.log(err);
})

10、Promise.all 和 Promise.allSettled 的实现

区分:

1、all是所有的Promise都变成fulfilled时, 再拿到结果,在拿到所有结果之前, 有一个promise变成了rejected, 那么整个promise是rejected

2、allSettled 无论是resolve还是reject,都有结果才会有最终的状态

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected' //状态来保证resolve后的reject是无效调用反之亦然
//抽取工具函数
function commonFunc(execFn, value, resolve, reject) {
    try {
        const result = execFn(value)
        resolve(result)
    } catch (err) {
        reject(err)
    }
}
class MyPromise {
    constructor(executor) {
        this.status = PROMISE_STATUS_PENDING
        this.value = undefined
        this.reason = undefined
        //多次调用需要用数组来接收
        this.onFulfilledFns = []
        this.onRejectedFns = []

        const resolve = (value) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onFulfilled() // this.onFulfilled is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_FULFILLED
                    this.value = value
                    this.onFulfilledFns.forEach(fn => {
                        fn(this.value)
                    })
                })

            }

        }
        const reject = (reason) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onRejected() // this.onRejected is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_REJECTED
                    this.reason = reason
                    this.onRejectedFns.forEach(fn => {
                        fn(this.reason)
                    })
                })

            }

        }
        //抛错处理一:
        try {
            executor(resolve, reject)
        } catch (err) {
            reject(err) // 这里可以捕获promise抛错
        }
    }
    //抛错处理二:
    then(onFulfilled, onRejected) {
        //新增catch方法的时候这里要新增几个优化点 - 不做处理会报 execFn is not a function
        // console.log(onRejected); // undefined 为什么undefined看最下面的解释
        const defaultOnRejected = err => {
            throw err
        }
        onRejected = onRejected || defaultOnRejected

        const defaultOnFulfilled = value => {
            return value
        }
        onFulfilled = onFulfilled || defaultOnFulfilled

        return new MyPromise((resolve, reject) => {
            // 1.如果在调用then的时候,状态是已经确定的情况
            if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
                commonFunc(onFulfilled, this.value, resolve, reject)
            }
            if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
                commonFunc(onRejected, this.reason, resolve, reject)
            }

            //2.状态未定的时候,将成功回调和失败的回调放到数组中
            if (this.status === PROMISE_STATUS_PENDING) {
                if (onFulfilled) this.onFulfilledFns.push(() => {
                    commonFunc(onFulfilled, this.value, resolve, reject)
                })
                if (onRejected) this.onRejectedFns.push(() => {
                    commonFunc(onRejected, this.reason, resolve, reject)
                })
            }
        })


    }

    catch (onRejected) {
        return this.then(undefined, onRejected)
    } 

    finally(onFinally) {
        this.then(() => {
            onFinally()
        }, () => {
            onFinally()
        })
    }

    static resolve(value) {
        return new MyPromise((resolve) => {
            resolve(value)
        })
    }

    static reject(reason) {
        return new MyPromise((resolve, reject) => {
            reject(reason)
        })
    }

    static all(promiseArr) {
        return new MyPromise((resolve, reject) => {
            let arr = []
            promiseArr.forEach(promise => {
                promise.then(res => {
                    arr.push(res)
                    if (arr.length === promiseArr.length) {
                        resolve(arr)
                    }
                }, err => {
                    reject(err)
                })
            })
        })
    }

    static allSettled(promiseArr) {
        return new MyPromise((resolve, reject) => {
            let arr = []
            promiseArr.forEach(promise => {
                promise.then(res => {
                    arr.push({
                        status: PROMISE_STATUS_FULFILLED,
                        value: res
                    })
                    if (arr.length === promiseArr.length) {
                        resolve(arr)
                    }
                }, err => {
                    arr.push({
                        status: PROMISE_STATUS_REJECTED,
                        value: err
                    })
                    if (arr.length === promiseArr.length) {
                        resolve(arr)
                    }
                })
            })
        })
    }
}

//实例化
const promise = new MyPromise((resolve, reject) => {
    console.log('状态pending');
    // throw new Error("promise中抛错") //promise中抛错
    resolve('我是resolve')
    reject('我是reject')
})

const p1 = new MyPromise((resolve) => {
    setTimeout(() => {
        resolve('one')
    }, 1000)
})
const p2 = new MyPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('two')
        // reject('two')
    }, 2000)
})
const p3 = new MyPromise((resolve) => {
    setTimeout(() => {
        resolve('three')
    }, 3000)
})

MyPromise.all([p1, p2, p3]).then(res => {
    console.log(res) //全是resolve的话 [ 'one', 'two', 'three' ]
}).catch(err => {
    console.log(err) //two
})

MyPromise.allSettled([p1, p2, p3]).then(res => {
    console.log(res)
    // [{
    //         status: 'fulfilled',
    //         value: 'one'
    //     },
    //     {
    //         status: 'fulfilled',
    //         value: 'two'
    //     },
    //     {
    //         status: 'fulfilled',
    //         value: 'three'
    //     }
    // ]
})

11、Promise.race 和 Promise.any 的实现

区分:

1、race 只要有一个Promise变成fulfilled状态, 那么就结束 

意外: 在都没有结果的时候有一个 先reject了就不等其他结果了,直接算拒绝的

2、any方法 会等到一个fulfilled状态才会决定,但是如果都是reject状态,那么要等到所有都变成reject的

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected' //状态来保证resolve后的reject是无效调用反之亦然
//抽取工具函数
function commonFunc(execFn, value, resolve, reject) {
    try {
        const result = execFn(value)
        resolve(result)
    } catch (err) {
        reject(err)
    }
}
class MyPromise {
    constructor(executor) {
        this.status = PROMISE_STATUS_PENDING
        this.value = undefined
        this.reason = undefined
        //多次调用需要用数组来接收
        this.onFulfilledFns = []
        this.onRejectedFns = []

        const resolve = (value) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onFulfilled() // this.onFulfilled is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_FULFILLED
                    this.value = value
                    this.onFulfilledFns.forEach(fn => {
                        fn(this.value)
                    })
                })

            }

        }
        const reject = (reason) => {
            if (this.status === PROMISE_STATUS_PENDING) {

                // this.onRejected() // this.onRejected is not a function 代码的执行顺序,这个在then前执行 - 引入微任务解决
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return //由于状态在then写了判断,这里又是异步,所以这里这里要多加一个判断
                    this.status = PROMISE_STATUS_REJECTED
                    this.reason = reason
                    this.onRejectedFns.forEach(fn => {
                        fn(this.reason)
                    })
                })

            }

        }
        //抛错处理一:
        try {
            executor(resolve, reject)
        } catch (err) {
            reject(err) // 这里可以捕获promise抛错
        }
    }
    //抛错处理二:
    then(onFulfilled, onRejected) {
        //新增catch方法的时候这里要新增几个优化点 - 不做处理会报 execFn is not a function
        // console.log(onRejected); // undefined 为什么undefined看最下面的解释
        const defaultOnRejected = err => {
            throw err
        }
        onRejected = onRejected || defaultOnRejected

        const defaultOnFulfilled = value => {
            return value
        }
        onFulfilled = onFulfilled || defaultOnFulfilled

        return new MyPromise((resolve, reject) => {
            // 1.如果在调用then的时候,状态是已经确定的情况
            if (this.status === PROMISE_STATUS_FULFILLED && onFulfilled) {
                commonFunc(onFulfilled, this.value, resolve, reject)
            }
            if (this.status === PROMISE_STATUS_REJECTED && onRejected) {
                commonFunc(onRejected, this.reason, resolve, reject)
            }

            //2.状态未定的时候,将成功回调和失败的回调放到数组中
            if (this.status === PROMISE_STATUS_PENDING) {
                if (onFulfilled) this.onFulfilledFns.push(() => {
                    commonFunc(onFulfilled, this.value, resolve, reject)
                })
                if (onRejected) this.onRejectedFns.push(() => {
                    commonFunc(onRejected, this.reason, resolve, reject)
                })
            }
        })


    }

    catch (onRejected) {
        return this.then(undefined, onRejected)
    }
    
    finally(onFinally) {
        this.then(() => {
            onFinally()
        }, () => {
            onFinally()
        })
    }

    static resolve(value) {
        return new MyPromise((resolve) => {
            resolve(value)
        })
    }

    static reject(reason) {
        return new MyPromise((resolve, reject) => {
            reject(reason)
        })
    }

    static all(promiseArr) {
        return new MyPromise((resolve, reject) => {
            let arr = []
            promiseArr.forEach(promise => {
                promise.then(res => {
                    arr.push(res)
                    if (arr.length === promiseArr.length) {
                        resolve(arr)
                    }
                }, err => {
                    reject(err)
                })
            })
        })
    }

    static allSettled(promiseArr) {
        return new MyPromise((resolve, reject) => {
            let arr = []
            promiseArr.forEach(promise => {
                promise.then(res => {
                    arr.push({
                        status: PROMISE_STATUS_FULFILLED,
                        value: res
                    })
                    if (arr.length === promiseArr.length) {
                        resolve(arr)
                    }
                }, err => {
                    arr.push({
                        status: PROMISE_STATUS_REJECTED,
                        value: err
                    })
                    if (arr.length === promiseArr.length) {
                        resolve(arr)
                    }
                })
            })
        })
    }

    //只要有一个Promise变成fulfilled状态, 那么就结束 在都没有结果的时候有一个先reject了就不等其他结果了,直接算拒绝的
    static race(promiseArr) {
        return new MyPromise((resolve, reject) => {
            promiseArr.forEach(promise => {
               promise.then(resolve, reject)
            })
        })
    }

    //会等到一个fulfilled状态才会决定,但是如果都是reject状态,那么要等到所有都变成reject的
    static any(promiseArr) {
        const arr = []
        return new MyPromise((resolve, reject) => {
            promiseArr.forEach(promise => {
                promise.then(resolve, err => {
                    arr.push(err)
                    if (arr.length === promises.length) {
                        reject(new AggregateError(arr)) //最新es12类型
                    }
                })
            })
        })
    }
}

//实例化
const promise = new MyPromise((resolve, reject) => {
    console.log('状态pending');
    // throw new Error("promise中抛错") //promise中抛错
    resolve('我是resolve')
    reject('我是reject')
})

const p1 = new MyPromise((resolve, reject) => {
    setTimeout(() => {
        reject('one')
    }, 3000)
})
const p2 = new MyPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('two')
    }, 2000)
})
const p3 = new MyPromise((resolve, reject) => {
    setTimeout(() => {
        reject('three')
    }, 3000)
})

// MyPromise.race([p1, p2, p3]).then(res => {
//   console.log("res:", res)
// }).catch(err => {
//   console.log("err:", err) //two
// })

MyPromise.any([p1, p2, p3]).then(res => { //需要去浏览器中测
    console.log("res:", res)  //two
}, err => {
    console.log("err2:", err.errors)
})

暂时就这么多~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值