从0开始实现es6 promise类

news2024/9/29 15:17:55

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

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

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

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

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

        callback(resolve, reject)
    }
}

        测试代码如下:

const p = new MyGoPromise((resolve, reject) => {
    resolve("success")
    // reject("fail")
})

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

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

// 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)
    }
}

        测试代码如下:

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实现的代码如下:

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)
        }
    }

        测试代码如下所示:

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的调用逻辑的修改):

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 异步任务

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

// !!! 输出顺序有误 原生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函数直接传入回调函数即可执行

console.log("start")
queueMicrotask(()=>{
    console.log("queueMicrotask")
})
console.log("end")

        2.  MutationObserver notice:only works in browser 子节点改变就会执行

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")

        3. setTimeout(callback, 0) 

  1.4.2  异步任务实现

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

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函数逻辑,将回调函数封装成异步任务执行,代码如下:

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,代码如下:

    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
    }

        测试代码如下:

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方法处理,代码如下所示:

    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
    }
}

        测试代码如下:

// 测试代码 -- 返回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对象是否一致即可,代码(包含测试代码)如下所示:

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对象,所以封装函数如下:

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)
        }
}

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

    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
    }

        测试代码如下:

// 测试代码
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状态一样,代码如下所示:

    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
    }

        测试代码如下:

// 测试代码
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回调里面的函数错误,修改部分代码如下:

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

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

        测试的代码如下所示:

// 测试代码
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方法,只是不管是成功回调还是失败回调都是同一个回调函数,实现代码如下:

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

        测试代码如下:

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直接返回。

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

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

        测试代码如下:

// 测试代码
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,实现的代码如下:

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

        测试代码如下:

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

 2.3 race方法实现

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

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)
            })
        })
    })
}

        测试代码如下:

// 测试代码
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,全部成功返回一个数组(按顺序),如果传入空数组直接返回空数组结果,实现代码如下:

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)
            })
        })
    }) 
}

        测试代码如下所示:

// 测试代码
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方法的实现,代码如下:

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)
            })
        })
    }) 
}

        测试代码如下所示:

// 测试代码
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的报错,是新代码如下:

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))
            })
        })
    })
}

        测试代码如下所示:

// 测试代码
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 完整代码展示

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))
                })
            })
        })
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2177133.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

win10安装Java闪退

问题:win10 在安装Java8时,电脑没有反应,出现闪退的现象。 1、打开设置找到“时间和语言” 2、找到“中文(简体,中国)” 3、点击“选项” 4、删除“百度输入法” 5、问题解决,再次安装Java

史上最细快速排序讲解(hoare,挖坑,双指针, 非递归)

文章目录 前言一、递归方法快排1. 递归主要思想2. 递归代码实现 二、hoare方法实现找基准值1. hoare思想2. hoare代码实现 三、挖坑方法实现找基准值1. 挖坑思想2. 挖坑代码实现 四、双指针方法实现找基准值1. lomuto前后指针法思想2. lomuto前后指针法代码实现 五、非递归方法…

第十四周:机器学习笔记

第十四周周报 摘要Abstract一、机器学习——Transformer(下)1. Transformer decoder1.1 autoregressive decoder(自回归解码器)1.2 Transformer decoder结构图1.3 non-autoregressive decoder(非自回归解码器&#xff…

24年最新 idea 插件开发教程,面试鸭插件技术实现!

大家好,我是松柏。今天给大家分享下这个JetBrains插件开发教程。 学习过程中可以参考开源项目:https://github.com/yuyuanweb/mianshiya-plugin 首先贴一下官方文档:https://plugins.jetbrains.com/docs/intellij/welcome.html 虽然这个文档…

【最新发布】Win10 22H2 19045.4957 正式版免费下载!

今日系统之家小编给大家分享2024年9月第二次更新的Windows10 22H2正式版系统,该版本系统基于最新Windows10 22H2 19045.4957 64位专业版进行离线制作,安全无毒,修复了使用某些环绕声技术时某些媒体的播放可能会停止等多项问题,系统…

基于C#开发的(CS界面)图书管理系统

图书管理系统项目开发说明书 项目简介 项目背景(选择这个项目的原因、前景,面向的用户,优势); 根据温州理工学院需要希望能够充分利用现代科技来提高图书管理的效率,在原有的办公系统基础上进行扩展&…

1. 如何在服务器上租GPU跑实验 (以AutoDL为例) - 深度学习·科研实践·从0到1

目录 前言 1. 在AutoDL上注册账号 2. 在算力市场选择GPU 3. 创建实例 4. 控制台-容器实例界面(核心) 4.1 无卡模式(常用) 5. 帮助文档 前言 好记性不如烂笔头,本专栏将详细记录下本人学习深度学习工程实践&…

Python通过Sqlalchemy框架实现增删改查

目录 简介 什么是SQLAlchemy? SQLAlchemy可以分为两个部分:Core和ORM。 一、首先安装sqlalchemy 二、在配置文件中添加数据库连接信息,我这里是Mysql 三、 创建数据库连接类,我这里是动态读取数据库的表字段,自动…

神器!GPT让大学生也能轻松实现架构师级的系统设计图

文章目录 零、前言一、实现架构师级的系统设计图操作指导系统背景功能细化 画用例图画系统架构设计图划分html页面画实体类图画服务层类图画时序图画数据库ER图 二、感受 零、前言 粉丝做毕业设计时,不会画架构图,问虚竹哥会不会画~ 虽然这…

基于微信小程序的空巢老人健康管理系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…

STM32引脚PB3、PB4、PA15作为输入输出的特殊配置

一、问题描述 简单描述: 最近做的一个项目中,PB3端口配置为输入,不管外部输入是高电平还是低电平,一直读取到的是低电平。 调试过程:在撰写代码过程中,又发现新的问题,Enter按键无法控制屏幕数…

电脑显示缺失msvcp140_1.dll怎样修复,5种快速修复方法让你快速修复

1. msvcp140_1.dll 定义 1.1 Microsoft Visual C 2015 Redistributable组件 msvcp140_1.dll 是 Microsoft Visual C 2015 Redistributable 的关键组件之一,扮演着至关重要的角色。以下是对 msvcp140_1.dll 的详细分析: 组件功能:msvcp140_…

《中国电子报》报道: 安宝特AR为产线作业者的“秘密武器

近日,中国电子报在其文章《下一代工业智能终端重新定义制造业》中对安宝特的增强现实(AR)解决方案给予了高度评价,称其为产线作业者的“秘密武器”。这一创新技术改变了传统制造业的作业方式,使得操作人员能够在生产过…

Ubuntu中交叉编译armadillo库

网上关于交叉编译armadillo库比较少,借鉴了一些但是在前几天编译时总是磕磕绊绊,于是写一个详细的编译过程。 交叉编译armadillo库包含两个步骤:交叉编译依赖库和交叉编译armadillo。armadillo官网介绍依赖库如下图所示: 需要注意…

【高性能内存池】page cache 5

page cache 1 page cache的框架2 central cache从page cache申请n页span的过程3 page cache 的结构3.1 page cache类框架3.2 central cache向page cache申请span3.3 获取k页的span page cache的结构和central cache是一样的,都是哈希桶的结构,并且挂载的…

JAVA全球互联同城速达国际版同城跑腿快递代取帮买帮送一体化服务系统源码

全球互联,便捷生活新篇章! 🌟 开篇:跨越国界的即时服务革命 在这个快节奏的时代,你是否也曾为忙碌的生活而烦恼?购物、取件、送物……这些日常琐事似乎总在不经意间占据了我们宝贵的时间。但现在&#xf…

003集—— CAD批量划线和text文字(CAD—C#二次开发入门)

本例通过for循环创建255条线,颜色不同,并在线的右端点处注记文字。 效果如下: 本文有个事务的封装函数,如下: private ObjectId AppendEntity(Entity entity) { ObjectId objectId; Database db HostApplication…

❤Node实现接口增删改查(文章为例)

❤Node实现接口增删改查(文章为例) 1、文章表的创建​ 接下来我们新建一个文章数据表article,实现对于文章部分的管理功能接口 根据文章我们创建一个对应的 SQL 数据表 javascript CREATE TABLE articles (id INT AUTO_INCREMENT PRIMAR…

亚马逊卖家如何利用自养号测评策略低成本提升销量?

在跨境电商的平台上,随着市场逐渐成熟与竞争的白热化,众多卖家正面临流量增长乏力与转化率提升困难的双重挑战。为了在这日益激烈的竞争环境中脱颖而出,卖家们纷纷加大投入,探索多样化的推广策略,但往往因策略不够精准…