js原理——手写promise

1.1 构造函数

        创建MyPromise并设置构造函数;

class MyPromise{
    constructor(func) {
        // 定义resolve/reject
        const resolve = (result) => {
            console.log('resolve执行',result)
        }
        const reject = (result) => {
            console.log('reject执行',result)
        }
        // 执行回调函数
        func(resolve,reject)
    }
}

1.2 状态与原因

        为MyPromise添加状态(pending:待定、fulfilled:已兑现、rejected:已拒绝)与原因;

// 状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{

    // 添加状态/原因
    state = PENDING
    result = undefined

    constructor(func) {
        // 修改状态pending -> fulfilled/rejected
        const resolve = (result) => {
            if(this.state === PENDING) {
                this.state = FULFILLED
                this.result = result
            }
        }
        const reject = (result) => {
            if(this.state === PENDING) {
                this.state = REJECTED
                this.result = result
            }
        }
        // 执行回调函数
        func(resolve,reject)
    }
}

1.3 .then方法

1.3.1 成功和失败的回调

......

class MyPromise{

    ......   

    then(onFulfilled,onRejected) {
        // 判断
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x
        onRejected = typeof onRejected === 'function' ? onRejected : x => { throw x }
        
        // 执行回调
        if(this.state === FULFILLED) {
            onFulfilled(this.result)
        } else if (this.state === REJECTED) {
            onRejected(this.result)
        }
    }
}

1.3.2 异步与多次调用 

......

class MyPromise{

    ......

    // 定义实例属性
    #handlers = []

    constructor(func) {
        const resolve = (result) => {
            if(this.state === PENDING) {

                ......

                // 调用成功回调
                this.#handlers.forEach(({onFulfilled}) => {
                    onFulfilled(this.result)
                })
            }
        }
        const reject = (result) => {
            if(this.state === PENDING) {

                ......

                // 调用失败回调
                this.#handlers.forEach(({onRejected}) => {
                    onRejected(this.result)
                })
            }
        }
        // 执行回调函数
        func(resolve,reject)
    }

    then(onFulfilled,onRejected) {
        
        ......
        
        // 执行回调
        if(this.state === FULFILLED) {
            onFulfilled(this.result)
        } else if (this.state === REJECTED) {
            onRejected(this.result)
        } else if (this.state === PENDING) {
            // 保存回调函数 等待resolve()或reject()执行
            this.#handlers.push({
                onFulfilled,onRejected
            })
        }
    }
}

1.4 异步任务

        封装异步任务函数:

// 封装函数
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.innerText = 'huihui'
    } else {
        setTimeout(callback,0)
    }
}


......


class MyPromise{

    ......

    then(onFulfilled,onRejected) {
        
        ......
        
        // 执行回调
        if(this.state === FULFILLED) {
            runAsynctask(() => {
                onFulfilled(this.result)
            })
        } else if (this.state === REJECTED) {
            runAsynctask(() => {
                onRejected(this.result)
            })
        } else if (this.state === PENDING) {
            this.#handlers.push({
                onFulfilled:() => {
                    runAsynctask(() => {
                        onFulfilled(this.result)
                    })
                },onRejected:() => {
                    runAsynctask(() => {
                        onRejected(this.result)
                    })
                }
            })
        }
    }
}

1.5 链式编程

1.5.1 处理异常/普通内容

    then(onFulfilled,onRejected) {
        // 判断
        ...
        
        // 返回promise实例
        const p = new MyPromise((resolve,reject) => {
            if(this.state === FULFILLED) {
                runAsynctask(() => {
                    try {
                        const x = onFulfilled(this.result)
                        resolve(x)
                    } catch(error) {
                        reject(error)
                    }
                })
            } else if (this.state === REJECTED) {
                ...
            } else if (this.state === PENDING) {
                ...
            }
        })
        
        return p
    }

1.5.2 处理返回promise

if(this.state === FULFILLED) {
    runAsynctask(() => {
       try {
          const x = onFulfilled(this.result)
          // 返回promise
          if (x instanceof MyPromise) {
             x.then(res => resolve(res),err => reject(err))
          } else {
             resolve(x)
          }
      } catch(error) {
          reject(error)
      }
    })
}

        1.5.3 处理重复引用

if(this.state === FULFILLED) {
    runAsynctask(() => {
        try {
            const x = onFulfilled(this.result)

            // 处理重复引用
            if (x === p) {
            // 抛出错误
                 throw new TypeError('Chaining cycle detected for promise #<Promise>')
            }
            ......
        }
    })
}

1.5.4 rejected状态

//抽取函数
function resolvePromise(p,x,resolve,reject) {
    if(x === p) {
        throw new TypeError('Chaining cycle detected for promise #<Promise>')
    }
    if (x instanceof MyPromise) {
        x.then(res => resolve(res), err => reject(err))
    } else {
        resolve(x)
    }
}
if(this.state === FULFILLED) {
    runAsynctask(() => {
        try {
            const x = onFulfilled(this.result)

            // 调用函数
            resolvePromise(p, x, resolve, reject)
        } catch(error) {
            reject(error)
        }
    })
} else if (this.state === REJECTED) {
    runAsynctask(() => {
        const x = onRejected(this.result)

        // 调用函数
        resolvePromise(p,x,resolve,reject)
    })
}

1.5.5 pending状态

else if (this.state === PENDING) {
    this.#handlers.push({
        onFulfilled:() => {
            runAsynctask(() => {
                try {
                    const x = onFulfilled(this.result)
                    resolvePromise(p,x,resolve,reject)
                } catch (error) {
                    reject(error)
                }
            })
        },onRejected:() => {
            runAsynctask(() => {
                try {
                    const x = onRejected(this.result)
                    resolvePromise(p,x,resolve,reject)
                } catch (error) {
                    reject(error)
                }
            })
        }
   })
}

1.6 实例方法

1.6.1 catch方法

class MyPromise{

    ......

    constructor(func) { ...... }

    then(onFulfilled,onRejected) { ...... }

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

1.6.2 finally方法

class MyPromise{

    ......

    constructor(func) { ...... }
    then(onFulfilled,onRejected) { ...... }
    catch(onRejected) {...... }

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

1.7 静态方法

1.7.1 resolve 方法

    // resolve方法返回已完成状态的promise对象
    static resolve(value) {
        if(value instanceof MyPromise) {
            return value
        }
        return new MyPromise((resolve) => {
            resolve(value)
        })
    }

 1.7.2 reject 方法

    // 返回rejected状态的Promise
    static reject(value) {
        return new MyPromise((undefined, reject) => {
          reject(value)
        })
    }

1.7.3 race方法

    // race方法等待任意一个请求完成后进行响应
    static race(promises) {
        return new MyPromise((resolve,reject) => {
            // 判断是否是数组
            if(!Array.isArray(promises)) {
                return reject(new TypeError('Argument is not iterable'))
            }
            promises.forEach(p => {
                MyPromise.resolve(p).then(res => { resolve(res) },err => { reject(err) })
            })
        })
    }

1.7.4 all方法

    static all(promises) {
        return new MyPromise((resolve,reject) => {
            if(!Array.isArray(promises)) {
                return reject(new TypeError('Argument is not iterable'))
            }
            promises.length === 0 && resolve(promises)
            const results = []
            let count = 0
            promises.forEach((p,index) => {
                MyPromise.resolve(p).then(res => {
                    results[index] = res
                    count++
                    // 处理所有兑现
                    count === promises.length && resolve(results)
                },err => {
                    // 处理第一个拒绝
                    reject(err)
                })
            })
        })
    }

1.7.5 allSettled方法

    // allSettled方法返回promise状态全部敲定的结果
    static allSettled(promises) {
        return new MyPromise((resolve,reject) => {
            if(!Array.isArray(promises)) {
                return reject(new TypeError('Argument is not iterable'))
            }
            promises.length === 0 && resolve(promises)

            // 等待全部敲定
            const results = []
            let count = 0
            promises.forEach((p,index) => {
                MyPromise.resolve(p).then(res => {
                    results[index] = {status:FULFILLED,value:res}
                    count++
                    count === promises.length && resolve(results)
                },err => {
                    results[index] = {status:REJECTED,reason:err}
                    count++
                    count === promises.length && resolve(results)
                })
            })
        })
    }

1.7.6 any 方法

    static any(promises) {
        return new MyPromise((resolve,reject) => {
            if(!Array.isArray(promises)){
                return reject(new TypeError('Argument is not iterable'))
            }
            promises.length === 0 && reject(new AggregateError(promises, 'All promises were rejected'))

            const errors = []
            let count = 0
            promises.forEach((p,index) => {
                MyPromise.resolve(p).then(res => {
                    // 第一个兑现
                    resolve(res)
                },err => {
                    // 全部拒绝
                    errors[index] = err
                    count++
                    count === promises.length && reject(new AggregateError(errors, 'All promises were rejected'))
                })
            })
        })
    }

2. 完整写法


// 封装函数
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.innerText = 'huihui'
    } else {
        setTimeout(callback,0)
    }
}

// 抽取函数
function resolvePromise(p, x, resolve, reject) {
    if (x === p) {
        throw new TypeError('Chaining cycle detected for promise #<Promise>')
    }
    if (x instanceof MyPromise) {
        x.then(res => resolve(res), err => reject(err))
    } else {
        resolve(x)
    }
}

// 状态
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MyPromise{

    // 添加状态/原因
    state = PENDING
    result = undefined

    // 定义实例属性
    #handlers = []

    constructor(func) {
        // 修改状态pending -> fulfilled/rejected
        const resolve = (result) => {
            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)
                })
            }
        }
        // 执行回调函数
        func(resolve,reject)
    }

    then(onFulfilled,onRejected) {
        // 判断
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x
        onRejected = typeof onRejected === 'function' ? onRejected : x => { throw x }
        
        // 返回promise实例
        const p = new MyPromise((resolve,reject) => {
            if(this.state === FULFILLED) {
                runAsynctask(() => {
                    try {
                        const x = onFulfilled(this.result)

                        // 调用函数
                        resolvePromise(p, x, resolve, reject)
                    } catch(error) {
                        reject(error)
                    }
                })
            } else if (this.state === REJECTED) {
                runAsynctask(() => {
                    const x = onRejected(this.result)

                    // 调用函数
                    resolvePromise(p,x,resolve,reject)
                })
            } else if (this.state === PENDING) {
                this.#handlers.push({
                    onFulfilled:() => {
                        runAsynctask(() => {
                            try {
                                const x = onFulfilled(this.result)
                                resolvePromise(p,x,resolve,reject)
                            } catch (error) {
                                reject(error)
                            }
                        })
                    },onRejected:() => {
                        runAsynctask(() => {
                            try {
                               const x = onRejected(this.result)
                               resolvePromise(p,x,resolve,reject)
                            } catch (error) {
                                reject(error)
                            }
                        })
                    }
                })
            }
        })
        
        return p
    }

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

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

    // resolve方法返回已完成状态的promise对象
    static resolve(value) {
        if(value instanceof MyPromise) {
            return value
        }
        return new MyPromise((resolve) => {
            resolve(value)
        })
    }

    // 返回rejected状态的Promise
    static reject(value) {
        return new MyPromise((undefined, reject) => {
          reject(value)
        })
    }

    // race方法等待任意一个请求完成后进行响应
    static race(promises) {
        return new MyPromise((resolve,reject) => {
            // 判断是否是数组
            if(!Array.isArray(promises)) {
                return reject(new TypeError('Argument is not iterable'))
            }
            promises.forEach(p => {
                MyPromise.resolve(p).then(res => { resolve(res) },err => { reject(err) })
            })
        })
    }

    static all(promises) {
        return new MyPromise((resolve,reject) => {
            if(!Array.isArray(promises)) {
                return reject(new TypeError('Argument is not iterable'))
            }
            promises.length === 0 && resolve(promises)
            const results = []
            let count = 0
            promises.forEach((p,index) => {
                MyPromise.resolve(p).then(res => {
                    results[index] = res
                    count++
                    // 处理所有兑现
                    count === promises.length && resolve(results)
                },err => {
                    // 处理第一个拒绝
                    reject(err)
                })
            })
        })
    }

    // allSettled方法返回promise状态全部敲定的结果
    static allSettled(promises) {
        return new MyPromise((resolve,reject) => {
            if(!Array.isArray(promises)) {
                return reject(new TypeError('Argument is not iterable'))
            }
            promises.length === 0 && resolve(promises)

            // 等待全部敲定
            const results = []
            let count = 0
            promises.forEach((p,index) => {
                MyPromise.resolve(p).then(res => {
                    results[index] = {status:FULFILLED,value:res}
                    count++
                    count === promises.length && resolve(results)
                },err => {
                    results[index] = {status:REJECTED,reason:err}
                    count++
                    count === promises.length && resolve(results)
                })
            })
        })
    }

    static any(promises) {
        return new MyPromise((resolve,reject) => {
            if(!Array.isArray(promises)){
                return reject(new TypeError('Argument is not iterable'))
            }
            promises.length === 0 && reject(new AggregateError(promises, 'All promises were rejected'))

            const errors = []
            let count = 0
            promises.forEach((p,index) => {
                MyPromise.resolve(p).then(res => {
                    // 第一个兑现
                    resolve(res)
                },err => {
                    // 全部拒绝
                    errors[index] = err
                    count++
                    count === promises.length && reject(new AggregateError(errors, 'All promises were rejected'))
                })
            })
        })
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值