编辑代码

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
    constructor(executor) {
        this.status = PENDING // 当前状态
        this.value = null // 成功的值
        this.reason = null // 失败的值
        this.onFulfilledCallbacks = [] //成功回调
        this.onRejectedCallbacks = [] // 失败回调
        // resolve和reject为什么要用箭头函数?
        // 如果直接调用的话,普通函数this指向的是window或者undefined
        // 用箭头函数就可以让this指向当前实例对象
        const resolve = (value) => {
            // 只有状态是等待,才执行状态修改
            if (this.status === PENDING) {
                this.status = FULFILLED // 更改状态
                this.value = value // 成功赋值
                // resolve里面将所有成功的回调拿出来执行
                this.onFulfilledCallbacks.forEach((fn) => fn(value))
            }
        }
        const reject = (reason) => {
            if (this.status === PENDING) {
                this.status = REJECTED // 更改状态
                this.reason = reason // 失败赋值
                // resolve里面将所有失败的回调拿出来执行
                this.onRejectedCallbacks.forEach((fn) => fn(reason))
            }
        }
        try {
            // 执行
            executor(resolve, reject)
        } catch (error) {
            reject(error)
        }
    }

    then(onFulfilled, onRejected) {
        // 保证onFulfilled 和onRejected为一个函数
        const realOnfulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value
        const realonRejected =
            typeof onRejected === 'function'
                ? onRejected
                : (reason) => {
                    throw reason
                }
        // 链式调用,直接return出去promise2
        const promise2 = new MyPromise((resolve, reject) => {
            // 成功的微任务
            const fulfilledMicrotask = () => {
                // 创建一个微任务等待promise2完成初始化
                queueMicrotask(() => {
                    try {
                        // 获取成功的结果
                        const x = realOnfulfilled(this.value)
                        // 传入resolvePromise集中处理
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                })
            }
            // 失败的微任务
            const rejectMicrotask = () => {
                // 创建一个微任务等待promise2完成初始化
                queueMicrotask(() => {
                    try {
                        // 获取失败的结果
                        const x = realonRejected(this.reason)
                        // 传入resolvePromise集中处理
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                })
            }
            // 当前状态做判断
            if (this.status === FULFILLED) {
                fulfilledMicrotask()
            } else if (this.status === REJECTED) {
                rejectMicrotask()
            } else if (this.status === PENDING) {
                // 等待
                // 因为不知道后面状态的变化情况,所以将成功回调和失败回调存储起来
                // 等到执行成功失败函数的时候再传递
                this.onFulfilledCallbacks.push(fulfilledMicrotask)
                this.onRejectedCallbacks.push(rejectMicrotask)
            }
        })
        return promise2
    }
    // 失败的错误捕获
    // Promise.prototype.catch()方法是.then(null, rejection)
    // 或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数
    catch(onRejected) {
        this.then(undefined, onRejected)
    }
    // finally()方法用于指定不管 Promise 对象最后状态如何,
    // 都会执行的操作。该方法是 ES2018 引入标准的。
    finally(fn) {
        return this.then(
            (value) => {
                return MyPromise.resolve(fn()).then(() => {
                    return value
                })
            },
            (reason) => {
                return MyPromise.resolve(fn()).then(() => {
                    throw reason
                })
            }
        )
    }
    // resolve 静态方法 通过 MyPromise.resolve()调用
    static resolve(parmeter) {
        // 如果传入 MyPromise 就直接返回
        if (parmeter instanceof MyPromise) {
            return parmeter
        }
        return new MyPromise((resolve) => {
            resolve(parmeter)
        })
    }
    // reject 静态方法 通过 MyPromise.reject()调用
    static reject(reason) {
        return new MyPromise((resolve, reject) => {
            reject(reason)
        })
    }
    // all的静态方法 通过 MyPromise.all()调用
    // 只要参数实例有一个变成rejected状态,包装实例就会变成rejected状态;
    // 如果所有参数实例都变成fulfilled状态,包装实例就会变成fulfilled状态。
    static all(promiseList) {
        return new MyPromise((resolve, reject) => {
            const result = []
            const length = promiseList.length
            let count = 0

            if (length === 0) {
                return resolve(result)
            }

            promiseList.forEach((promise, index) => {
                // 保证是一个promise
                MyPromise.resolve(promise).then(
                    (value) => {
                        count++
                        result[index] = value
                        if (count === length) {
                            resolve(result)
                        }
                    },
                    (reason) => {
                        reject(reason)
                    }
                )
            })
        })
    }
    // any 的静态方法 通过 MyPromise.any()调用 es2021加入 和all刚好相反
    // 只要参数实例有一个变成fulfilled状态,包装实例就会变成fulfilled状态;
    // 如果所有参数实例都变成rejected状态,包装实例就会变成rejected状态。
    static any(promiseList) {
        return new MyPromise((resolve, reject) => {
            let count = 0
            let result = []
            let len = promiseList.length
            if (len === 0) return resolve(result)
            promiseList.forEach((item) => {
                // 保证是一个promise
                MyPromise.resolve(item).then(
                    (value) => {
                        resolve(value)
                    },
                    (reason) => {
                        count++
                        result.push(reason)
                        if (count === len) {
                            reject(result)
                        }
                    }
                )
            })
        })
    }
    // allSettled 的静态方法 通过 MyPromise.allSettled()调用
    // ES2020 引入了Promise.allSettled()方法 用来确定一组异步操作是否都结束了(不管成功或失败)
    //返回格式: [
    //    { status: 'fulfilled', value: value},
    //    { status: 'rejected', reason: reason }
    // ]
    static allSettled(promiseList) {
        return new MyPromise((resolve) => {
            const length = promiseList.length
            const result = []
            let count = 0

            if (length === 0) {
                return resolve(result)
            } else {
                for (let i = 0; i < length; i++) {
                    const currentPromise = MyPromise.resolve(promiseList[i])
                    currentPromise.then(
                        (value) => {
                            count++
                            result[i] = {
                                status: 'fulfilled',
                                value: value,
                            }
                            if (count === length) {
                                return resolve(result)
                            }
                        },
                        (reason) => {
                            count++
                            result[i] = {
                                status: 'rejected',
                                reason: reason,
                            }
                            if (count === length) {
                                return resolve(result)
                            }
                        }
                    )
                }
            }
        })
    }
    // race 的静态方法 通过 MyPromise.race()调用
    // 只要有个实例决议后就返回改该决议后的结果
    static race(promiseList) {
        return new MyPromise((resolve, reject) => {
            const length = promiseList.length

            if (length === 0) {
                return resolve()
            } else {
                for (let i = 0; i < length; i++) {
                    MyPromise.resolve(promiseList[i]).then(
                        (value) => {
                            return resolve(value)
                        },
                        (reason) => {
                            return reject(reason)
                        }
                    )
                }
            }
        })
    }
}

function resolvePromise(promise, x, resolve, reject) {
    if (promise === x) {
        return reject(new TypeError('cycle....'))
    }
    if ((typeof x === 'object' || typeof x === 'function') && x !== null) {
        let then
        try {
            then = x.then
        } catch (error) {
            return reject(error)
        }
        if (typeof then === 'function') {
            let called = false
            try {
                then.call(
                    x,
                    (y) => {
                        if (called) return
                        called = true
                        resolvePromise(promise, y, resolve, reject)
                    },
                    (r) => {
                        if (called) return
                        called = true
                        reject(r)
                    }
                )
            } catch (error) {
                if (called) return
                reject(error)
            }
        } else {
            resolve(x)
        }
    } else {
        resolve(x)
    }
}
MyPromise.deferred = function () {
    var result = {}
    result.promise = new MyPromise(function (resolve, reject) {
        result.resolve = resolve
        result.reject = reject
    })

    return result
}

// 值穿透
MyPromise.resolve(1)
    .then(2)
    .then(Promise.resolve(3))
    .then(console.log)
MyPromise.resolve(1)
    .then(() => { return 2 })
    .then(() => { return 3 })
    .then(console.log)

MyPromise.resolve(1)
    .then(function () {
        return 2
    })
    .then(() => { Promise.resolve(3) })
    .then(console.log)
MyPromise.reject(1)
    .then(res => {
        console.log(res);
    })
    .then(res => { console.log(res) },
        rej => {
            console.log(`rej****${rej}`);
        })
    .catch(err => {
        console.log(`err****${err}`);
    })

const resolved = MyPromise.resolve(42);
const rejected = MyPromise.reject(-1);

const allSettledPromise = MyPromise.allSettled([resolved, rejected]);

allSettledPromise.then(function (results) {
  console.log(results);
});

module.exports = MyPromise