piramis执行机制(运行顺序)

在平时的开发中经常使用到piramis,但我们使用的都是经过大佬封装后的成果,其实我们并不太了解真正的执行机制和顺序,这里我自己研究了下,下面做个记录并分享出来:

        const PENDING = 'pending'; // 定义待定状态的常量
        const FULFILLED = 'fulfilled'; // 定义已完成状态的常量
        const REJECTED = 'rejected'; // 定义已拒绝状态的常量

        class MyPiramis { // 定义 MyPiramis 类
            #status = PENDING; // 私有字段,用于存储状态,默认为待定状态
            #result = undefined; // 私有字段,用于存储结果,默认为未定义
            #resolveCallbacks = []; // 私有数组,用于存储解决回调函数
            #rejectCallbacks = []; // 私有数组,用于存储拒绝回调函数

            constructor(executor) { // 构造函数
                const resolve = (data) => { // 解决函数,用于将状态更改为已完成并执行解决回调函数
                    console.log(data, '函数resolve中的data'); // 记录解决函数中接收到的数据
                    setTimeout(() => { // 使用 setTimeout 模拟异步行为
                        console.log('执行函数resolve中setTimeout'); // 记录解决函数中的 setTimeout 执行
                        this.#changeStatus(FULFILLED, data); // 将状态更改为已完成
                        this.#resolveCallbacks.forEach(fn => fn(data)); // 执行所有解决回调函数
                        this.#resolveCallbacks = []; // 清空解决回调函数列表,避免内存泄漏
                        this.#rejectCallbacks = []; // 清空拒绝回调函数列表,避免内存泄漏
                    });
                };

                const rejected = (err) => { // 拒绝函数,用于将状态更改为已拒绝并执行拒绝回调函数
                    setTimeout(() => { // 使用 setTimeout 模拟异步行为
                        console.log('执行函数reject中setTimeout'); // 记录拒绝函数中的 setTimeout 执行
                        this.#changeStatus(REJECTED, err); // 将状态更改为已拒绝
                        this.#rejectCallbacks.forEach(fn => fn(err)); // 执行所有拒绝回调函数
                        this.#resolveCallbacks = []; // 清空解决回调函数列表,避免内存泄漏
                        this.#rejectCallbacks = []; // 清空拒绝回调函数列表,避免内存泄漏
                    });
                };

                try {
                    console.log('执行函数executor'); // 记录执行 executor 函数
                    executor(resolve, rejected); // 执行带有 resolve 和 rejected 函数的 executor 函数
                } catch (err) {
                    console.log(err, '函数executor中的err'); // 记录 executor 函数中出现的任何错误
                    rejected(err); // 如果出现错误,则调用 rejected 函数
                }
            }

            #changeStatus(status, data) { // 更改状态和结果的私有方法
                console.log(this.#status,'设置状态'); // 记录设置状态
                if (this.#status !== PENDING) return; // 如果状态不是待定,则不执行任何操作
                this.#status = status; // 更新状态为提供的状态
                this.#result = data; // 将结果设置为提供的数据
            }

            then(onFulfilled, onRejected) { // 注册完成和拒绝的回调函数的方法
                console.log('执行函数中then方法'); // 记录 then 方法的执行

                return new MyPiramis((resolve, rejected) => { // 返回 MyPiramis 的新实例

                    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => { }; // 确保 onFulfilled 是一个函数
                    onRejected = typeof onRejected === 'function' ? onRejected : () => { }; // 确保 onRejected 是一个函数

                    if (this.#status === PENDING) { // 如果状态是待定,则将回调函数添加到相应的数组中
                        console.log('函数中then方法的pending状态'); // 记录待定状态
                        this.#resolveCallbacks.push(onFulfilled); // 将 onFulfilled 添加到解决回调函数中
                        this.#rejectCallbacks.push(onRejected); // 将 onRejected 添加到拒绝回调函数中
                    }

                    if (this.#status === FULFILLED) { // 如果状态是已完成,则执行 onFulfilled
                        setTimeout(() => { // 使用 setTimeout 模拟异步行为
                            try {
                                console.log('函数中then方法的fulfilled状态的setTimeout中try'); // 记录 setTimeout 中的 try 块
                                onFulfilled(this.#result); // 执行 onFulfilled,并传递结果
                            } catch (err) {
                                console.log('函数中then方法的fulfilled状态的setTimeout中catch'); // 记录 setTimeout 中的 catch 块
                                rejected(err); // 如果出现错误,则调用 rejected 函数
                            }
                        });
                    }

                    if (this.#status === REJECTED) { // 如果状态是已拒绝,则执行 onRejected
                        setTimeout(() => { // 使用 setTimeout 模拟异步行为
                            try {
                                console.log('函数中then方法的rejected状态的setTimeout中try'); // 记录 setTimeout 中的 try 块
                                onRejected(this.#result); // 执行 onRejected,并传递结果
                            } catch (err) {
                                console.log('函数中then方法的rejected状态的setTimeout中catch'); // 记录 setTimeout 中的 catch 块
                                rejected(err); // 如果出现错误,则调用 rejected 函数
                            }
                        });
                    }
                });
            }
        }

上边每一段代码都有注释,console.log的主要目的就是为了看清楚执行顺序。

下面展示下不同情况下的执行顺序:

let p = new MyPiramis((resolve, rejected) => { // 使用 executor 函数创建 MyPiramis 的新实例
            console.log('进入p中'); // 记录进入 executor 函数
            resolve('嘿哈'); // 使用 '嘿哈' 进行解决
            // throw 'error'
            // rejected('失败'); // 使用 '失败' 进行拒绝
        })
        p.then(
            (data) => { // 完成处理程序
                console.log(data, '成功data'); // 记录成功数据
            },
            (err) => { // 拒绝处理程序
                console.log(err, '失败err'); // 记录错误
            }
        )

这里的执行打印结果为:

执行函数executor
进入p中
嘿哈 函数resolve中的data
执行函数中then方法
执行函数executor
函数中then方法的pending状态
执行函数resolve中setTimeout
 pending 设置状态
嘿哈 成功data

 let p = new MyPiramis((resolve, rejected) => { // 使用 executor 函数创建 MyPiramis 的新实例
            console.log('进入p中'); // 记录进入 executor 函数
            resolve('嘿哈'); // 使用 '嘿哈' 进行解决
            throw 'error'
            rejected('失败'); // 使用 '失败' 进行拒绝
        })
        p.then(
            (data) => { // 完成处理程序
                console.log(data, '成功data'); // 记录成功数据
            },
            (err) => { // 拒绝处理程序
                console.log(err, '失败err'); // 记录错误
            }
        )

执行结果:

执行函数executor
进入p中
嘿哈 函数resolve中的data
error 函数executor中的err
执行函数中then方法
执行函数executor
函数中then方法的pending状态
执行函数resolve中setTimeout
pending 设置状态
嘿哈 成功data
执行函数reject中setTimeout
fulfilled 设置状态

这里可以对比着原始的piramis去试验一下,这样看执行过程就很清晰了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值