从0开始实现es6 promise类

主要由基础实现和静态类的实现两部分组成。

1 基础实现(不含静态类)

1.1 使用类实现完成构造函数

实现代码如下,构造函数传入一个回调函数,定义resolve和reject函数,将两个函数作为参数执行回调函数。

javascript 复制代码
// 1. 使用类实现,完成构造函数
class MyGoPromise{
    constructor(callback){
        const resolve = (result) => {
            console.log(result)
        }
        const reject = (result) => {
            console.log(result)
        }

        callback(resolve, reject)
    }
}

测试代码如下:

javascript 复制代码
const p = new MyGoPromise((resolve, reject) => {
    resolve("success")
    // reject("fail")
})

1.2 实现状态(pending fulfilled rejected)及结果

首先状态在类内直接声明默认值,状态固定为三个,声明为类外的字符串常量使用。实现在reject和resolve调用时候的状态变化(pending -> fulfilled, pending --> rejected)以及结果保存。代码实现如下所示:

javascript 复制代码
// 2. 状态及原因 state(pending fulfilled rejected) result
// 常量最好单独定义,方便维护
const PENDING = "pending"
const FULFILLED = "fulfilled"
const REJECTED = "rejected"
class MyGoPromise{
    state = PENDING
    result = undefined
    constructor(callback){
        const resolve = (result) => {
            // 状态只能从pending变为fulfilled或者rejected
            if(this.state === PENDING){
                this.state = FULFILLED
                this.result = result
            }
        }
        const reject = (result) => {
            if(this.state === PENDING){
                this.state = REJECTED
                this.result = result
            }
        }
        callback(resolve, reject)
    }
}

测试代码如下:

javascript 复制代码
const p = new MyGoPromise((resolve, reject) => {
    resolve("success")
    // reject("fail")
})
console.log(p)

1.3 then的基础实现

1.3.1 then的成功以及失败回调实现(同步)

then接收两个回调函数,成功回调以及失败的回调,通过查阅文档得知传入非函数时,成功返回为x => x,失败返回为 x => throw x。然后根据状态执行相应的回调函数。then实现的代码如下:

javascript 复制代码
then(onFulFilled, onRejected){
        onFulFilled = typeof onFulFilled === "function" ? onFulFilled : x => x
        onRejected = typeof onRejected === "function" ? onRejected : e => {throw e}
        if(this.state === FULFILLED){
            onFulFilled(this.result)
        }
        else if(this.state === REJECTED){
            onRejected(this.result)
        }
    }

测试代码如下所示:

javascript 复制代码
const p = new MyGoPromise((resolve, reject) => {
    // resolve("success")
    reject("fail")
})

p.then(res => {console.log(res)}, err => {console.log(err)})
console.log(p)

1.3.2 then的异步支持以及多次调用

之前的then执行的都是同步任务,需要加入对如setTimeout等异步执行的支持,修改then函数,增加判断条件pending,成立将回调暂存到隐私函数handlers中,等到rejecet或resolve时再执行,修改的代码如下(包含then和reject和resolve的调用逻辑的修改):

javascript 复制代码
constructor(callback){
        const resolve = (result) => {
            // 状态只能从pending变为fulfilled或者rejected
            if(this.state === PENDING){
                this.state = FULFILLED
                this.result = result
                this.#handlers.forEach(({onFulFilled}) => {onFulFilled(this.result)})
            }
        }
        const reject = (result) => {
            if(this.state === PENDING){
                this.state = REJECTED
                this.result = result
                this.#handlers.forEach(({onRejected}) => {onRejected(this.result)})
            }
        }

        callback(resolve, reject)
    }

then(onFulFilled, onRejected){
        // 当传入的值不是函数时,需要按照以下两种形式返回
        onFulFilled = typeof onFulFilled === "function" ? onFulFilled : x => x
        onRejected = typeof onRejected === "function" ? onRejected : e => {throw e}
        if(this.state === FULFILLED){
            onFulFilled(this.result)
        }
        else if(this.state === REJECTED){
            onRejected(this.result)
        }
        else{
            this.#handlers.push({
                onFulFilled,
                onRejected
            })
        }
    }
}

1.4 异步任务

当我们使用下述代码测试我们已经实现的内容时会发现输出的顺序错误,代码如下所示:

javascript 复制代码
// !!! 输出顺序有误 原生Promise输出为 start end success
// !!! 自定义Promise输出为 start success end
// 所以需要引入异步任务 选用核心API queueMicrotask MutationObserver setTimeout
console.log("start")
const p = new MyGoPromise((resolve, reject) => {
    resolve("success")
})
p.then(res => console.log(res))
console.log("end")

1.4.1 异步主要API

  1. queueMicrotask函数直接传入回调函数即可执行
javascript 复制代码
console.log("start")
queueMicrotask(()=>{
    console.log("queueMicrotask")
})
console.log("end")
  1. MutationObserver notice:only works in browser 子节点改变就会执行
javascript 复制代码
console.log("start")
const obs = new MutationObserver(()=>{
    console.log("MutationObserver")
})

const divNode = document.createElement("div")
obs.observe(divNode, {childList: true})
divNode.innerHTML = "MyGo!!!!!"
console.log("end")
  1. setTimeout(callback, 0)

1.4.2 异步任务实现

将异步任务执行封装成全局函数调用,用于判断以上三种异步实现浏览器是否支持,实现的runAsyncTask函数如下所示:

javascript 复制代码
function runAsyncTask(callback){
    if(typeof queueMicrotask === "function"){
        queueMicrotask(callback)
    }else if(typeof MutationObserver === "function"){
        const obs = new MutationObserver(callback)
        const divNode = document.createElement("div")
        obs.observe(divNode, {childList: true})
        divNode.innerHTML = "MyGo!!!!!"
    }else{
        setTimeout(callback, 0)
    }
}

修改then函数逻辑,将回调函数封装成异步任务执行,代码如下:

javascript 复制代码
then(onFulFilled, onRejected){
        // 当传入的值不是函数时,需要按照以下两种形式返回
        onFulFilled = typeof onFulFilled === "function" ? onFulFilled : x => x
        onRejected = typeof onRejected === "function" ? onRejected : e => {throw e}
        if(this.state === FULFILLED){
            // 异步任务
            runAsyncTask(()=>{
                onFulFilled(this.result)
            })    
        }
        else if(this.state === REJECTED){
            // 异步任务
            runAsyncTask(()=>{
                onRejected(this.result)
            })
        }
        else{
            this.#handlers.push({
                onFulFilled:() => {
                    // 异步任务
                    runAsyncTask(()=>{
                        onFulFilled(this.result)
                    })
                },
                onRejected: () =>{
                    // 异步任务
                    runAsyncTask(() => {
                        onRejected(this.result)
                    })
                }
            })
        }
    }

1.5 链式编程

链式编程实现then的链式调用,错误处理,返回值处理(通常分为返回Promise 正常值 多重引用)。

1.5.1 处理异常和普通返回值(fulfilled state)

首先实现链式调用,使用new再then函数中创建一个全新的Promise对象,将对象返回,将之前then函数的执行逻辑放入新的Promise的回调函数当中(因为会立即执行),单独处理fulfilled分支使用try...catch...捕获错误,使用reject返回错误,获取回调函数返回值,然后resolve,代码如下:

javascript 复制代码
    then(onFulFilled, onRejected){
        // 当传入的值不是函数时,需要按照以下两种形式返回
        onFulFilled = typeof onFulFilled === "function" ? onFulFilled : x => x
        onRejected = typeof onRejected === "function" ? onRejected : e => {throw e}

        // 在newPromise时传入的回调函数会立即执行
        const newPromise = new MyGoPromise((resolve, reject) => {
            if(this.state === FULFILLED){
                // 异步任务
                runAsyncTask(()=>{
                    try {
                        const x = onFulFilled(this.result)
                        resolve(x)
                    } catch (error) {
                        reject(error) 
                    }
                }) 
              
            }
            else if(this.state === REJECTED){
                // 异步任务
                runAsyncTask(()=>{
                    onRejected(this.result)
                })
            }
            else{
                this.#handlers.push({
                    onFulFilled:() => {
                        // 异步任务
                        runAsyncTask(()=>{
                            onFulFilled(this.result)
                        })
                    },
                    onRejected: () =>{
                        // 异步任务
                        runAsyncTask(() => {
                            onRejected(this.result)
                        })
                    }
                })
            }
        })
        return newPromise
    }

测试代码如下:

javascript 复制代码
const p = new MyGoPromise((resolve, reject) => {
    resolve(1)
})

p.then(res =>{
    console.log(res)
    // throw "error layer1"
    return 100
}).then(res =>{
    console.log(res + " sub")
}, err =>{
    console.log(err + "sub")
})

1.5.2 处理返回Promise对象 (fulfilled state)

使用instance of判断,promise对象调用then方法处理,代码如下所示:

javascript 复制代码
    then(onFulFilled, onRejected){
        // 当传入的值不是函数时,需要按照以下两种形式返回
        onFulFilled = typeof onFulFilled === "function" ? onFulFilled : x => x
        onRejected = typeof onRejected === "function" ? onRejected : e => {throw e}

        // 在newPromise时传入的回调函数会立即执行
        const newPromise = new MyGoPromise((resolve, reject) => {
            if(this.state === FULFILLED){
                // 异步任务
                runAsyncTask(()=>{
                    try {
                        const x = onFulFilled(this.result)
                        // 在这里处理Promise对象根据结果提交
                        if(x instanceof MyGoPromise){
                            x.then(res =>{
                                resolve(res)
                            }, err =>{
                                reject(err)
                            })
                        }else{
                            resolve(x)
                        }

                    } catch (error) {
                        reject(error) 
                    }
                }) 
              
            }
            else if(this.state === REJECTED){
                // 异步任务
                runAsyncTask(()=>{
                    onRejected(this.result)
                })
            }
            else{
                this.#handlers.push({
                    onFulFilled:() => {
                        // 异步任务
                        runAsyncTask(()=>{
                            onFulFilled(this.result)
                        })
                    },
                    onRejected: () =>{
                        // 异步任务
                        runAsyncTask(() => {
                            onRejected(this.result)
                        })
                    }
                })
            }
        })
        return newPromise
    }
}

测试代码如下:

javascript 复制代码
// 测试代码 -- 返回Promise对象
const p = new MyGoPromise((resolve, reject) => {
    resolve(1)
})

p.then(res =>{
    return new MyGoPromise((resolve, reject) => {
        // resolve(2)
        reject("error layer2")
    })
}).then(res =>{
    // 要拿到上一个Promise resolve的结果
    console.log(res + " sub")
}, err =>{
    console.log(err + "sub")
})

1.5.3 处理重复引用 (fulfilled state)

只需要判断我们取到的回调函数的返回值和创建的新的promise对象是否一致即可,代码(包含测试代码)如下所示:

javascript 复制代码
if(x === newPromise)
{
    throw new TypeError("Chaining cycle detected for promise")
}


// test code
const p = new MyGoPromise((resolve, reject) => {
    resolve(1)
})

const p2 = p.then((res)=>{
    return p2
})

1.5.4 处理rejected state 封装函数

遵循同一套逻辑,首先进行错误处理,然后判断重复引用和回调结果是否是Promise对象,所以封装函数如下:

javascript 复制代码
function resolvePromise(newPromise, x, resolve, reject){
    if(x === newPromise)
        {
            throw new TypeError("Chaining cycle detected for promise")
        }
        if(x instanceof MyGoPromise){
            x.then(res =>{
                resolve(res)
            }, err =>{
                reject(err)
            })
        }else{
            resolve(x)
        }
}

使用封装函数,代码如下:

javascript 复制代码
    then(onFulFilled, onRejected){
        // 当传入的值不是函数时,需要按照以下两种形式返回
        onFulFilled = typeof onFulFilled === "function" ? onFulFilled : x => x
        onRejected = typeof onRejected === "function" ? onRejected : e => {throw e}

        // 在newPromise时传入的回调函数会立即执行
        const newPromise = new MyGoPromise((resolve, reject) => {
            if(this.state === FULFILLED){
                // 异步任务
                runAsyncTask(()=>{
                    try {
                        const x = onFulFilled(this.result)
                        resolvePromise(newPromise, x, resolve, reject)
                    } catch (error) {
                        reject(error) 
                    }
                }) 
              
            }
            else if(this.state === REJECTED){
                // 异步任务
                runAsyncTask(()=>{
                    try {
                        const x = onRejected(this.result)
                        resolvePromise(newPromise, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                    
                })
            }
            else{
                this.#handlers.push({
                    onFulFilled:() => {
                        // 异步任务
                        runAsyncTask(()=>{
                            onFulFilled(this.result)
                        })
                    },
                    onRejected: () =>{
                        // 异步任务
                        runAsyncTask(() => {
                            onRejected(this.result)
                        })
                    }
                })
            }
        })
        return newPromise
    }

测试代码如下:

javascript 复制代码
// 测试代码
const p = new MyGoPromise((resolve, reject) => {
    reject(1)
})

const p2 = p.then(undefined, res =>{
    // return 2
    // return p2
    throw "error"
    // return new MyGoPromise((resolve, reject) => {
    //     resolve(3)
    // })
})

p2.then((res)=>{
    console.log("p2-res: ", res)
}, err =>(
    console.log("p2-err: ", err)
))

1.5.5 处理pending state 调用函数

和处理fulfilled和rejected状态一样,代码如下所示:

javascript 复制代码
    then(onFulFilled, onRejected){
        // 当传入的值不是函数时,需要按照以下两种形式返回
        onFulFilled = typeof onFulFilled === "function" ? onFulFilled : x => x
        onRejected = typeof onRejected === "function" ? onRejected : e => {throw e}

        // 在newPromise时传入的回调函数会立即执行
        const newPromise = new MyGoPromise((resolve, reject) => {
            if(this.state === FULFILLED){
                // 异步任务
                runAsyncTask(()=>{
                    try {
                        const x = onFulFilled(this.result)
                        resolvePromise(newPromise, x, resolve, reject)
                    } catch (error) {
                        reject(error) 
                    }
                }) 
              
            }
            else if(this.state === REJECTED){
                // 异步任务
                runAsyncTask(()=>{
                    try {
                        const x = onRejected(this.result)
                        resolvePromise(newPromise, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                    
                })
            }
            else{
                this.#handlers.push({
                    onFulFilled:() => {
                        // 异步任务
                        runAsyncTask(()=>{
                            try {
                                const x = onFulFilled(this.result)
                                resolvePromise(newPromise, x, resolve, reject)
                            } catch (error) {
                                reject(error)
                            }
                        })
                    },
                    onRejected: () =>{
                        // 异步任务
                        runAsyncTask(() => {
                            try {
                                const x = onRejected(this.result)
                                resolvePromise(newPromise, x, resolve, reject)
                            } catch (error) {
                                reject(error)
                            }
                        })
                    }
                })
            }
        })
        return newPromise
    }

测试代码如下:

javascript 复制代码
// 测试代码
const p = new MyGoPromise((resolve, reject) => {
    setTimeout(()=>{
        resolve("success")
    }, 2000)
})

const p2 = p.then(res =>{
    // return 2
    // return p2
    throw "error"
    // return new MyGoPromise((resolve, reject) => {
    //     resolve(3)
    // })
})

p2.then((res)=>{
    console.log("p2-res: ", res)
}, err =>(
    console.log("p2-err: ", err)
))

1.6 实现catch方法

处理错误,相当于调用then方法,但是还要处理new Promise回调里面的函数错误,修改部分代码如下:

javascript 复制代码
    
//新增catch函数
catch(onRejected){
        // 相当于变相调用then方法
    return this.then(undefined, onRejected)
}

// 处理实例化时的异常
    try {
        callback(resolve, reject)
    } catch (error) {
            // 处理实例化时的异常
        reject(error)
    }

测试的代码如下所示:

javascript 复制代码
// 测试代码
const p = new MyGoPromise((resolve, reject) => {
    throw "error"
    // reject("reject-error")
})

p.then((res)=>{
    console.log("p-res: ", res)
}).catch(err =>(
    console.log("p-catch-err: ", err)
))

1.7 finally实现

不管是什么状态,最终都要执行的回调函数,也是调用then方法,只是不管是成功回调还是失败回调都是同一个回调函数,实现代码如下:

javascript 复制代码
finally(onFinally){
    return this.then(onFinally, onFinally)
}

测试代码如下:

javascript 复制代码
const p = new MyGoPromise((resolve, reject) => {
    throw "error"
    // reject("reject-error")
})

p.then((res)=>{
    console.log("p-res: ", res)
}).catch(err =>(
    console.log("p-catch-err: ", err)
)).finally(()=>{
    console.log("finally")
})

2 静态类方法实现

2.1 resolve方法实现

调用该方法将传入的值(非Promise)转换为fulfilled状态的Promise返回,如果传入Promise直接返回。

javascript 复制代码
static resolve(value){
    if(value instanceof MyGoPromise){
        return value
    }

    return new MyGoPromise((resolve) => {
        resolve(value)
    })
}

测试代码如下:

javascript 复制代码
// 测试代码
const p = MyGoPromise.resolve(
    new MyGoPromise((resolve, reject) => {
        // resolve("success")
        reject("reject-error")
    })
).then(res =>{
    console.log("res: ", res)
}, err =>{
    console.log("err: ", err)
})

2.2 reject方法实现

不管传入什么值,直接将返回值作为原因返回rejected状态的promise,实现的代码如下:

javascript 复制代码
static reject(value){
    return new MyGoPromise((resolve, reject) => {
        reject(value)
    })
}

测试代码如下:

javascript 复制代码
// 测试代码
MyGoPromise.reject("reject-error").catch(err =>{
    console.log("err: ", err)
})

2.3 race方法实现

race接收一个数组作为参数,返回最先完成(fulfilled)的promise对象,如果传入不是数组则拨错,实现代码如下:

javascript 复制代码
static race(promises){
    return new MyGoPromise((resolve, reject) => {
        if(!Array.isArray(promises)){
            reject(new TypeError("Argument is not iterable"))
        }

        promises.forEach(promise =>{
            MyGoPromise.resolve(promise).then(res => {
                resolve(res)
            }, err =>{
                reject(err)
            })
        })
    })
}

测试代码如下:

javascript 复制代码
// 测试代码
const p1 = new MyGoPromise((resolve, reject) => {
    setTimeout(()=>{
        resolve("success")
    }, 2000)
})

const p2 = new MyGoPromise((resolve, reject) => {
    setTimeout(()=>{
        reject("reject-error")
    }, 1000)
})

MyGoPromise.race([p1, p2]).then(res =>{
    console.log("res: ", res)
}, err =>{
    console.log("err: ", err)
})

2.4 all方法实现

也是传入一个数组,有一个错误就reject,全部成功返回一个数组(按顺序),如果传入空数组直接返回空数组结果,实现代码如下:

javascript 复制代码
static all(promises){
    // 1.返回Promise实例
    // 2.判断是否时数组
    // 3. 判断是否为空数组,空数组直接兑现
    // 4. 处理全部兑现 v,k 存储数据, count计数判断是否拒绝
    // 5. 处理拒绝 直接拒绝即可
    return new MyGoPromise((resolve, reject) => {
        if(!Array.isArray(promises)){
            reject(new TypeError("Argument is not iterable"))
        }
        promises.length === 0 && resolve([])

        let count = 0
        const result = []
        promises.forEach((promise, index) => {
            MyGoPromise.resolve(promise).then(res =>{
                result[index] = res
                count ++
                count === promises.length && resolve(result)
            }, err =>{
                reject(err)
            })
        })
    }) 
}

测试代码如下所示:

javascript 复制代码
// 测试代码
const p1 = new MyGoPromise((resolve, reject) => {
    setTimeout(()=>{
        resolve("success 1")
    }, 2000)
})

const p2 = new MyGoPromise((resolve, reject) => {
    setTimeout(()=>{
        resolve("success 2")
    }, 1000)
})

MyGoPromise.all([p1, p2]).then(res =>{
    console.log("res: ", res)
}, err =>{
    console.log("err: ", err)
})

2.5 allsettled方法实现

无论成功还是失败,都是返回一个对象数组,数组中存储state和value以及reason,基本照搬all方法的实现,代码如下:

javascript 复制代码
static allsettled(promises){
    return new MyGoPromise((resolve, reject) => {
        if(!Array.isArray(promises)){
            reject(new TypeError("Argument is not iterable"))
        }
        promises.length === 0 && resolve([])

        let count = 0
        const result = []
        promises.forEach((promise, index) => {
            MyGoPromise.resolve(promise).then(res =>{
                result[index] = {
                    value: res,
                    status: "fulfilled",
                }
                count ++
                count === promises.length && resolve(result)
            }, err =>{
                result[index] = {
                    reason: err,
                    status: "rejected"
                }
                count ++
                count === promises.length && resolve(result)
            })
        })
    }) 
}

测试代码如下所示:

javascript 复制代码
// 测试代码
const p1 = new MyGoPromise((resolve, reject) => {
    setTimeout(()=>{
        resolve("success 1")
    }, 2000)
})

const p2 = new MyGoPromise((resolve, reject) => {
    setTimeout(()=>{
        reject("success 2")
    }, 1000)
})

MyGoPromise.allsettled([1, p1, p2]).then(res =>{
    // 会打印成功和失败的结果
    console.log("res: ", res)
}, err =>{
    console.log("err: ", err)
})

2.6 any方法实现

任意一个成功就返回成功,全部失败才返回失败,和all反着来,但是在any方法中,如果传入空数组也会有aggregate的报错,是新代码如下:

javascript 复制代码
static any(promises){
    return new MyGoPromise((resolve, reject)=>{
        if(!Array.isArray(promises)){
            reject(new TypeError("Argument is not iterable"))
        }
        promises.length === 0 && reject(new AggregateError([]))

        let count = 0
        const errors = []

        promises.forEach((promise, index)=>{
            MyGoPromise.resolve(promise).then(res => {
                resolve(res)
            }, err => {
                errors[index] = err
                count ++
                count === promises.length && reject(new AggregateError(errors))
            })
        })
    })
}

测试代码如下所示:

javascript 复制代码
// 测试代码
const p1 = new MyGoPromise((resolve, reject) => {
    setTimeout(()=>{
        resolve("success 1")
    }, 2000)
})

const p2 = new MyGoPromise((resolve, reject) => {
    setTimeout(()=>{
        reject("success 2")
    }, 1000)
})

MyGoPromise.any([p1, p2, MyGoPromise.reject(1)]).then(res =>{
    // 会打印第一个成功的结果 1
    console.log("res: ", res)
}, err =>{
    console.log("err: ", err)
})

3 完整代码展示

javascript 复制代码
function runAsyncTask(callback){
    if(typeof queueMicrotask === "function"){
        queueMicrotask(callback)
    }else if(typeof MutationObserver === "function"){
        const obs = new MutationObserver(callback)
        const divNode = document.createElement("div")
        obs.observe(divNode, {childList: true})
        divNode.innerHTML = "MyGo!!!!!"
    }else{
        setTimeout(callback, 0)
    }
}

function resolvePromise(newPromise, x, resolve, reject){
    if(x === newPromise)
        {
            throw new TypeError("Chaining cycle detected for promise")
        }
        if(x instanceof MyGoPromise){
            x.then(res =>{
                resolve(res)
            }, err =>{
                reject(err)
            })
        }else{
            resolve(x)
        }
}

const PENDING = "pending"
const FULFILLED = "fulfilled"
const REJECTED = "rejected"
class MyGoPromise{
    state = PENDING
    result = undefined
    // 使用对象数组保存pending时候的失败调用和成功调用
    #handlers = []
    constructor(callback){
        const resolve = (result) => {
            // 状态只能从pending变为fulfilled或者rejected
            if(this.state === PENDING){
                this.state = FULFILLED
                this.result = result
                this.#handlers.forEach(({onFulFilled}) => {onFulFilled(this.result)})
            }
        }
        const reject = (result) => {
            if(this.state === PENDING){
                this.state = REJECTED
                this.result = result
                this.#handlers.forEach(({onRejected}) => {onRejected(this.result)})
            }
        }

        try {
            callback(resolve, reject)
        } catch (error) {
            // 处理实例化时的异常
            reject(error)
        }
        
    }

    then(onFulFilled, onRejected){
        // 当传入的值不是函数时,需要按照以下两种形式返回
        onFulFilled = typeof onFulFilled === "function" ? onFulFilled : x => x
        onRejected = typeof onRejected === "function" ? onRejected : e => {throw e}

        // 在newPromise时传入的回调函数会立即执行
        const newPromise = new MyGoPromise((resolve, reject) => {
            if(this.state === FULFILLED){
                // 异步任务
                runAsyncTask(()=>{
                    try {
                        const x = onFulFilled(this.result)
                        resolvePromise(newPromise, x, resolve, reject)
                    } catch (error) {
                        reject(error) 
                    }
                }) 
              
            }
            else if(this.state === REJECTED){
                // 异步任务
                runAsyncTask(()=>{
                    try {
                        const x = onRejected(this.result)
                        resolvePromise(newPromise, x, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                    
                })
            }
            else{
                this.#handlers.push({
                    onFulFilled:() => {
                        // 异步任务
                        runAsyncTask(()=>{
                            try {
                                const x = onFulFilled(this.result)
                                resolvePromise(newPromise, x, resolve, reject)
                            } catch (error) {
                                reject(error)
                            }
                        })
                    },
                    onRejected: () =>{
                        // 异步任务
                        runAsyncTask(() => {
                            try {
                                const x = onRejected(this.result)
                                resolvePromise(newPromise, x, resolve, reject)
                            } catch (error) {
                                reject(error)
                            }
                        })
                    }
                })
            }
        })
        return newPromise
    }

    catch(onRejected){
        // 相当于变相调用then方法
        return this.then(undefined, onRejected)
    }

    finally(onFinally){
        return this.then(onFinally, onFinally)
    }

    static resolve(value){
        if(value instanceof MyGoPromise){
            return value
        }

        return new MyGoPromise((resolve) => {
            resolve(value)
        })
    }

    static reject(value){
        return new MyGoPromise((resolve, reject) => {
            reject(value)
        })
    }

    static race(promises){
        return new MyGoPromise((resolve, reject) => {
            if(!Array.isArray(promises)){
                reject(new TypeError("Argument is not iterable"))
            }

            promises.forEach(promise =>{
                MyGoPromise.resolve(promise).then(res => {
                    resolve(res)
                }, err =>{
                    reject(err)
                })
            })
        })
    }

    static all(promises){
        // 1.返回Promise实例
        // 2.判断是否时数组
        // 3. 判断是否为空数组,空数组直接兑现
        // 4. 处理全部兑现 v,k 存储数据, count计数判断是否拒绝
        // 5. 处理拒绝 直接拒绝即可
        return new MyGoPromise((resolve, reject) => {
            if(!Array.isArray(promises)){
                reject(new TypeError("Argument is not iterable"))
            }
            promises.length === 0 && resolve([])

            let count = 0
            const result = []
            promises.forEach((promise, index) => {
                MyGoPromise.resolve(promise).then(res =>{
                    result[index] = res
                    count ++
                    count === promises.length && resolve(result)
                }, err =>{
                    reject(err)
                })
            })
        }) 
    }


    static allsettled(promises){
        return new MyGoPromise((resolve, reject) => {
            if(!Array.isArray(promises)){
                reject(new TypeError("Argument is not iterable"))
            }
            promises.length === 0 && resolve([])

            let count = 0
            const result = []
            promises.forEach((promise, index) => {
                MyGoPromise.resolve(promise).then(res =>{
                    result[index] = {
                        value: res,
                        status: "fulfilled",
                    }
                    count ++
                    count === promises.length && resolve(result)
                }, err =>{
                    result[index] = {
                        reason: err,
                        status: "rejected"
                    }
                    count ++
                    count === promises.length && resolve(result)
                })
            })
        }) 
    }

    static any(promises){
        return new MyGoPromise((resolve, reject)=>{
            if(!Array.isArray(promises)){
                reject(new TypeError("Argument is not iterable"))
            }
            promises.length === 0 && reject(new AggregateError([]))

            let count = 0
            const errors = []

            promises.forEach((promise, index)=>{
                MyGoPromise.resolve(promise).then(res => {
                    resolve(res)
                }, err => {
                    errors[index] = err
                    count ++
                    count === promises.length && reject(new AggregateError(errors))
                })
            })
        })
    }

}
相关推荐
徐_三岁22 分钟前
Vue3实现mqtt的订阅与发布
前端
itas1091 小时前
Electron获取nodejs和chrome版本信息
javascript·chrome·electron·nodejs·node
qq_544329171 小时前
从0学习React(5)---通过例子体会setState
前端·学习·react.js
xcLeigh2 小时前
HTML5实现好看的唐朝服饰网站模板源码2
前端·html·html5
安冬的码畜日常2 小时前
【玩转 JS 函数式编程_004】1.4 如何应对 JavaScript 的不同版本
开发语言·前端·javascript·ecmascript·函数式编程·fp·functional
iQM752 小时前
TinyVue:一款轻量级且功能强大的Vue UI组件库
前端·javascript·vue.js·ui·jenkins·excel
学习使我快乐012 小时前
JS进阶 1——作用域、解构、箭头函数
开发语言·javascript·ecmascript
howard20052 小时前
初试React前端框架
前端·react.js·前端框架
蜗牛快跑2133 小时前
DOM元素导出图片与PDF:多种方案对比与实现
前端·javascript·pdf
小彭努力中3 小时前
50. GLTF格式简介 (Web3D领域JPG)
前端·3d·webgl