Promise的设计结构与手写(二)

198 阅读3分钟

跟着coderwhy学习

1.Promise结构的设计

const PROMISE_STATUS_PENDING = 'pending'
const PROMISE_STATUS_FULFILLED = 'fulfilled'
const PROMISE_STATUS_REJECTED = 'rejected'

class myPromise {
    constructor(executor) {
        this.status = PROMISE_STATUS_PENDING
        this.value = undefined
        this.reason = undefined

        const resolve = (value) => {
            if (this.status === PROMISE_STATUS_FULFILLED) {
                this.status = PROMISE_STATUS_FULFILLED
                this.value = value
                console.log('resolve被调用')
            }
        }

        const reject = (reason) => {
            if (this.status === PROMISE_STATUS_FULFILLED) {
                this.status = PROMISE_STATUS_REJECTED
                this.reason = reason
                console.log("reject被调用")
            }
        }

        executor(resolve, reject)
    }
}

const promise = new myPromise((resolve, reject) => {
    console.log('状态pending')
    resolve(1111)
    reject(2222)
})

promise.then(res => {

}, err => {

})

window.onclick = function () {

}

2. then方法设计

...

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
                queueMicrotask(() => {
                    this.value = value
                    this.onFulfilled(this.value)
                });
            }
        }

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

        executor(resolve, reject)
    }

    then(onFulfilled, onRejected) {
        this.onFulfilled = onFulfilled
        this.onRejected = onRejected
    }
}
  • then方法设计优化一
class myPromise {
    constructor(executor) {
        ...
        this.onFulfilledFns = []
        this.onRejectedFns = []

        const resolve = (value) => {
            if (this.status === PROMISE_STATUS_PENDING) {
                // 添加微任务
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return
                    this.status = PROMISE_STATUS_FULFILLED
                    this.value = value
                    this.onFulfilledFns.forEach(fn => {
                        fn(this.value)
                    })
                })
            }
        }

        const reject = (reason) => {
            if (this.status === PROMISE_STATUS_PENDING) {
                // 添加微任务
                queueMicrotask(() => {
                    if (this.status !== PROMISE_STATUS_PENDING) return
                    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)
        }
    }
}
  • then方法设计优化二
// 工具函数
function execFunctionWithCatchError(execFn, value, resolve, reject) {
    try {
        const result = execFn(value)
        resolve(result)
    } catch (err) {
        reject(err)
    }
}

class myPromise {
    constructor(executor) {
        ...
        try {
            executor(resolve, reject)
        } catch (err) {
            reject(err)
        }
    }

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

            // 2.将成功回调和失败的回调放到数组中
            if (this.status === PROMISE_STATUS_PENDING) {
                this.onFulfilledFns.push(() => {
                    // try {
                    //   const value = onFulfilled(this.value)
                    //   resolve(value)
                    // } catch(err) {
                    //   reject(err)
                    // }
                    execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
                })
                this.onRejectedFns.push(() => {
                    // try {
                    //   const reason = onRejected(this.reason)
                    //   resolve(reason)
                    // } catch(err) {
                    //   reject(err)
                    // }
                    execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
                })
            }
        })
    }
}

3.catch方法设计

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

4.finally方法设计

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

5.reslove和reject方法设计

...
static resolve(value) {
    return new myPromise((resolve) => resolve(value))
}

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

myPromise.resolve("Hello World").then(res => {
    console.log("res:", res)
})

myPromise.reject("Error Message").catch(err => {
    console.log("err:", err)
})

6.all和allSetted方法设计

 static all(promises) {
     // 问题关键: 什么时候要执行resolve, 什么时候要执行reject
      return new myPromise((resolve, reject) => {
            const values = []
            promises.forEach(promise => {
                promise.then(res => {
                    values.push(res)
                    if (values.length === promises.length) {
                        resolve(values)
                    }
                }, err => {
                    reject(err)
                })
            })
        })
    }

    static allSettled(promises) {
        return new myPromise((resolve) => {
            const results = []
            promises.forEach(promise => {
                promise.then(res => {
                    results.push({status: PROMISE_STATUS_FULFILLED, value: res})
                    if (results.length === promises.length) {
                        resolve(results)
                    }
                }, err => {
                    results.push({status: PROMISE_STATUS_REJECTED, value: err})
                    if (results.length === promises.length) {
                        resolve(results)
                    }
                })
            })
        })
    }
}

const p1 = new Promise((resolve) => {
    setTimeout(() => {
        resolve(1111)
    }, 1000)
})
const p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject(2222)
    }, 2000)
})
const p3 = new Promise((resolve) => {
    setTimeout(() => {
        resolve(3333)
    }, 3000)
})
// myPromise.all([p1, p2, p3]).then(res => {
//   console.log(res)
// }).catch(err => {
//   console.log(err)
// })

myPromise.allSettled([p1, p2, p3]).then(res => {
    console.log(res)
})

7.rece和any方法设计

    static race(promises) {
        return new myPromise((resolve,reject) => {
            promises.forEach(promises => {
                // promise.then(res => {
                //   resolve(res)
                // }, err => {
                //   reject(err)
                // })
                promise.then(resolve,reject)
            })
        })
    }

    static any(promises) {
        // resolve必须等到有一个成功的结果
        // reject所有的都失败才执行reject
        const reasons = []
        return new myPromise((resolve, reject) => {
            promises.forEach(promise => {
                promise.then(resolve, err => {
                    reasons.push(err)
                    if (reasons.length === promises.length) {
                        reject(new AggregateError(reasons))
                    }
                })
            })
        })
    }
}

const p1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject(1111)
    }, 1000)
})
const p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject(2222)
    }, 2000)
})
const p3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject(3333)
    }, 3000)
})

myPromise.any([p1, p2, p3]).then(res => {
    console.log("res:", res)
}).catch(err => {
    console.log("err:", err.errors) // [1111, 2222, 3333]
})

简单总结手写Promise

一. Promise规范

promisesaplus.com/

二. Promise类设计

class myPromise {}
function myPromise() {}

三.构造函数的规划

class myPromise {
    constructor(executor) {
        // 定义状态
        // 定义resolve、reject回调
        // resolve执行微任务队列:改变状态、获取value、then传入执行成功回调
        // reject执行微任务队列:改变状态、获取reason、then传入执行失败回调

        // try catch
        executor(resolve, reject)
    }
}

四.then方法的实现

class myPromise {
    then(onFullied, onRejected) {
        // this.onFulfilled = onFulfilled
        // this.onRejected = onRejected

        // 1.判断onFulfilled、onRejected,会给默认值

        // 2.返回Promise resolve/reject

        // 3.判断之前的promise状态是否确定
        // onFulfilled/onRejected直接执行(捕获异常)

        // 4.添加到数组中push(() => { 执行 onFulfilled/onRejected 直接执行代码})
    }
}

五. catch方法

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

六. finally

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

七. resolve/reject

八. all/allSettled

核心:要知道new Promise的resolve、reject在什么情况下执行

all:

  • 情况一:所有的都有结果
  • 情况二:有一个reject

allSettled:

  • 情况:所有都有结果,并且一定执行resolve

九.race/any

race:

  • 情况:只要有结果

any:

  • 情况一:必须等到一个resolve结果
  • 情况二:都没有resolve,所有的都是reject