• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

mandyGuan12

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

promise

手写promise --核心功能-->方法-->promise/A+

参考

mdn--promise
.
.

promise中的核心功能

构造函数

    /**
     * 构造函数
     * 1. 定义类
     * 2. 添加构造函数
     * 3. 定义resolve/reject
     * 4. 执行回调函数
    */

    class myPromise {
        constructor(func) {
            const resolve = (result) => {
                console.log('resolve 执行: ' + result);
            }
            const reject = (result) => {
                console.log('reject 执行: ' + result);
            }
            func(resolve, reject)
        }
    }

    // 测试用例
    const p = new myPromise((resolve, reject) => {
        resolve('success')
        // reject('error')
    })

.

状态及原因

一个 Promise 必然处于以下几种状态之一:
待定(pending):初始状态,既没有被兑现,也没有被拒绝。
已兑现(fulfilled):意味着操作成功完成。
已拒绝(rejected):意味着操作失败。
一个待定的 Promise 最终状态可以是已兑现并返回一个值,或者是已拒绝并返回一个原因(错误)。当其中任意一种情况发生时,通过 Promise 的 then 方法串联的处理程序将被调用。如果绑定相应处理程序时 Promise 已经兑现或拒绝,这处理程序将被立即调用,因此在异步操作完成和绑定处理程序之间不存在竞态条件。

如果一个 Promise 已经被兑现或拒绝,即不再处于待定状态,那么则称之为已敲定(settled)。即状态不可逆。
.

    const PENDING = 'pending'
    const FULFILLED = 'fullfilled'
    const REJECTED = 'reject'

    class myPromise {
        // 1. 添加状态
        state = PENDING
        // 2. 添加原因
        result = undefined

        constructor(func) {
            const resolve = (result) => {
                // 3. 调整状态 
                // 4. 添加原因
                if (this.state === PENDING) {
                    this.state = FULFILLED
                    this.result = result
                }
            }
            const reject = (result) => {
                // 3. 调整状态 
                // 4. 添加原因
                if (this.state === PENDING) {
                    this.state = REJECTED
                    this.result = result
                }
            }
            func(resolve, reject)
        }
    }
    // 测试用例
    const p = new myPromise((resolve, reject) => {
        resolve('success')
        reject('error')
        // 状态已敲定为fulfilled, 即便执行reject也不会改变状态了
    })

.

then方法

> 成功和失败回调

onFulfilled 可选
一个在此 Promise 对象被兑现时异步执行的函数。它的返回值将成为 then() 返回的 Promise 对象的兑现值。此函数被调用时将传入以下参数:
value
Promise 对象的兑现值。

如果 onFulfilled 不是一个函数,则内部会被替换为一个恒等函数((x) => x),它只是简单地将兑现值向前传递。

onRejected 可选
一个在此 Promise 对象被拒绝时异步执行的函数。它的返回值将成为 catch() 返回的 Promise 对象的兑现值。此函数被调用时将传入以下参数:
reason
Promise 对象被拒绝的原因。

如果 onRejected 不是一个函数,则内部会被替换为一个抛出器函数((x) => { throw x; }),它会抛出它收到的拒绝原因。

    const PENDING = 'pending'
    const FULFILLED = 'fullfilled'
    const REJECTED = 'reject'

    class myPromise {
        state = PENDING
        result = undefined

        constructor(func) {
            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. 添加实例方法
        then(onFulfilled, onRejected) {
            // 2. 参数判断
            onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x
            onRejected = typeof onRejected === 'function' ? onRejected : x => { throw x }
            // 3. 分情况执行回调
            if (this.state === FULFILLED) {
                onFulfilled(this.result)
            } else if (this.state === REJECTED) {
                onRejected(this.result)
            }
        }
    }

    // 测试用例
    const p = new myPromise((resolve, reject) => {
        // resolve('success')
        reject('error')
    })
    p.then(res => {
        console.log("回调成功: ", res);
    }, err => {
        console.log("回调失败: ", err);
    })

> 异步和多次调用

   const PENDING = 'pending'
    const FULFILLED = 'fullfilled'
    const REJECTED = 'reject'

    class myPromise {
        state = PENDING
        result = undefined
        // 1. 定义实例属性, 保存传入的回调函数, 用对象数组来存
        #handlers = []


        constructor(func) {
            const resolve = (result) => {
                if (this.state === PENDING) {
                    this.state = FULFILLED
                    this.result = result
                    // 3. 调用成功回调
                    this.#handlers.forEach(({ onFulfilled }) => {
                        onFulfilled(this.result)
                    })
                }
            }
            const reject = (result) => {
                if (this.state === PENDING) {
                    this.state = REJECTED
                    this.result = result
                    // 4. 调用失败回调
                    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 }
            if (this.state === FULFILLED) {
                onFulfilled(this.result)
            } else if (this.state === REJECTED) {
                onRejected(this.result)
            } else if (this.state === PENDING) {
                // 2. 保存回调函数
                this.#handlers.push({
                    onFulfilled, onRejected
                })
            }
        }
    }

    // 测试用例
    const p = new myPromise((resolve, reject) => {
        setTimeout(() => {
            resolve('success')
            reject('error')
        }, 2000)
    })

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

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

.

异步任务

> 核心api

为了实现异步任务, vue2使用的核心api有: Promise.then、MutationObserver 、 setImmediate 、 setTimeout

这里我们选用: queueMicrotask 、MutationObserver 、 setTimeout

使用 queueMicrotask 注册的回调函数会在当前宏任务的所有同步代码执行完毕后,但在下一个宏任务(如 DOM 更新、渲染等)开始之前执行。

MutationObserver 接口提供了一种异步监视 DOM 变动的能力。当 DOM 发生变化时,MutationObserver 会触发回调函数。

setTimeout 函数用于设置一个定时器,该定时器在指定的延迟时间后执行一个函数或指定的代码片段。

开启异步任务:

// 1. 异步任务 ==> queueMicrotask
    console.log(1);
    queueMicrotask(() => {
        console.log('queueMicrotask');
    })
    console.log('2');

    // 2. 异步任务 ==> MutationObeserver
    console.log(1);
    // 创建并返回一个新的观察器,它会在触发指定 DOM 事件时,调用指定的回调函数
    const mo = new MutationObserver(() => {
        console.log('mutationObserver');
    })
    // 创建
    const divDom = document.createElement('div')
    // 监听子节点改变
    mo.observe(divDom, { childList: true })
    // 修改内容触发回调函数
    divDom.innerText = 'hehe'
    console.log('2');

    // 3. 异步任务 ==> setTimeout
    console.log(1);
    setTimeout(() => {
        console.log('setTimeout');
    }, 0)
    console.log(2);

.

> 函数封装

       then(onFulfilled, onRejected) {
            onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x
            onRejected = typeof onRejected === 'function' ? onRejected : x => { throw x }
            // 3. 使用封装函数
            if (this.state === FULFILLED) {
                myAsync(() => {
                    onFulfilled(this.result)
                })

            } else if (this.state === REJECTED) {
                myAsync(() => {
                    onRejected(this.result)
                })

            } else if (this.state === PENDING) {
                this.#handlers.push({
                    onFulfilled: () => {
                        myAsync(() => {
                            onFulfilled(this.result)
                        })
                    },
                    onRejected: () => {
                        myAsync(() => {
                            onRejected(this.result)
                        })
                    }
                })
            }
        }
    }

    // 1. 定义函数
    function myAsync(callback) {
        // 2. 调用核心api
        if (typeof queueMicrotask === 'function') {
            queueMicrotask(callback)
        } else if (typeof MutationObserver === 'function') {
            const mo = new MutationObserver(callback)
            const divDom = document.createElement('div')
            mo.observe(divDom, { childList: true })
            divDom.innerText = 'hehe'
        } else {
            setTimeout(callback, 0)
        }

    }

    // 测试用例
    console.log('top');
    const p = new myPromise((resolve, reject) => {
        resolve('success')
        reject('error')
    })
    p.then(res => {
        console.log("then: ", res);
    }, err => {
        console.log("then: ", err);
    })
    console.log('bottom');

.
.
.

链式编程

由于这些方法返回 Promise,因此它们可以被链式调用。

.

FULFILLED状态下处理返回值和异常

        then(onFulfilled, onRejected) {
            onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : x => x
            onRejected = typeof onRejected === 'function' ? onRejected : x => { throw x }

            // 1. 返回新的promise实例
            const p2 = new myPromise((resolve, reject) => {
                if (this.state === FULFILLED) {
                    myAsync(() => {
                        try {
                            // 2. 获取返回值
                            const x = onFulfilled(this.result)
                            // console.log(x);
                            // 3. 处理返回值
                            resolve(x)
                        } catch (error) {
                            reject(error)
                        }
                    })

                } else if (this.state === REJECTED) {
                    myAsync(() => {
                        onRejected(this.result)
                    })

                } else if (this.state === PENDING) {
                    this.#handlers.push({
                        onFulfilled: () => {
                            myAsync(() => {
                                onFulfilled(this.result)
                            })
                        },
                        onRejected: () => {
                            myAsync(() => {
                                onRejected(this.result)
                            })
                        }
                    })
                }
            })
            return p2
        }
    }

   // 测试用例
    const p = new myPromise((resolve, reject) => {
        resolve('1')
        // reject('error')
    })
    p.then(res => {
        console.log("p1: ", res);
        throw 'throw error'
        return 2
    }).then(res => {
        console.log("p2: ", res)
    }, err => {
        console.log("p2: ", err);
    })

.
.

FULFILLED状态下处理返回promise

myAsync(() => {
                        try {
                            const x = onFulfilled(this.result)
                            // 1. 处理返回的promise
                            if (x instanceof myPromise) {
                                // 2. 调用then方法
                                x.then(res => resolve(res), err => reject(err))
                            } else {
                                resolve(x)
                            }

                        } catch (error) {
                            reject(error)
                        }
                    }

// 测试用例
    const p = new myPromise((resolve, reject) => {
        resolve('1')

    })
    p.then(res => {
        return new myPromise((resolve, reject) => {
            // resolve(2)
            reject('error')
        })
    }).then(res => {
        console.log("p2: ", res)
    }, err => {
        console.log("p2: ", err);
    })

.
.

FULFILLED状态下处理重复引用

try {
                            const x = onFulfilled(this.result)
                            // 1. 处理重复的引用
                            if (x === p2) {
                                // 2. 抛出错误
                                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 p = new myPromise((resolve, reject) => {
        resolve(1)

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

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

.
.

REJECTED状态

else if (this.state === REJECTED) {
                    myAsync(() => {
                        // 1. 处理异常
                        try {
                            // 2. 获取返回值
                            const x = onRejected(this.result)
                            // 4. 调用函数
                            resovlePromise(p2, x, resolve, reject)
                        } catch (error) {
                            reject(error)
                        }

                    })

                }


// 3. 抽取函数
    function resovlePromise(p2, x, resolve, reject) {
        if (x === p2) {
            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 p = new myPromise((resolve, reject) => {
        reject(1)

    })
    const p2 = p.then(undefined, err => {
        // throw 'error'
        // return p2
        // return 2
        return new myPromise((resolve, reject) => {
            resolve('myPromise-2')
        })
    })

    p2.then(
        res => { console.log('p2-res', res); },
        err => console.log('p2-err', err)
    )

.
.

PENDING状态

else if (this.state === PENDING) {
                    this.#handlers.push({
                        onFulfilled: () => {
                            myAsync(() => {
                                try {
                                    const x = onFulfilled(this.result)
                                    resovlePromise(p2,x,resolve,reject)
                                } catch (error) {
                                    reject(error)
                                }

                            })
                        },
                        onRejected: () => {
                            myAsync(() => {
                                try {
                                    const x = onRejected(this.result)
                                    resovlePromise(p2,x,resolve,reject)
                                } catch (error) {
                                    reject(error)
                                }

                            })
                        }
                    })
                }
            }

// 测试用例
    const p = new myPromise((resolve, reject) => {
        setTimeout(() => {
            resolve(1)
        }, 2000)
    })
    const p2 = p.then(res => {
        throw 'error'
        // return p2
        // return 2
        // return new myPromise((resolve, reject) => {
        //     resolve('resolve-2')
        //     reject('reject-2')
        // })
    })

    p2.then(
        res => { console.log('p2-res', res); },
        err => console.log('p2-err', err)
    )

.
.
.

promise中的实例方法

.catch()方法

Promise.prototype.catch()
将一个拒绝处理回调函数附加到 Promise 上,并返回一个新的 Promise,如果回调被调用,则解决为回调的返回值,如果 Promise 被兑现,解决为其原始兑现值。

Promise 实例的 catch() 方法用于注册一个在 promise 被拒绝时调用的函数。它会立即返回一个等效的 Promise 对象,这可以允许你链式调用其他 promise 的方法。此方法是 Promise.prototype.then(undefined, onRejected) 的一种简写形式。

Promise.prototype.finally()
将一个处理器附加到 Promise 上,并返回一个新的 Promise,当原始 Promise 被解决时解决。无论 Promise 是否被兑现还是被拒绝,处理器都会在 Promise 敲定时被调用。

posted on 2024-09-07 17:52  番茄仔Mandy  阅读(20)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3