软件教程 2025年08月6日
0 收藏 0 点赞 434 浏览 6349 个字
摘要 :

文章目录 一、Promise与then方法的实现 二、catch方法的实现 三、finally方法的实现 四、Promise类方法的实现 (一)resolve方法 (二)reject方法 (三)race方法 (……




  • 一、Promise与then方法的实现
  • 二、catch方法的实现
  • 三、finally方法的实现
  • 四、Promise类方法的实现
    • (一)resolve方法
    • (二)reject方法
    • (三)race方法
    • (四)all方法
    • (五)allSettled方法

    Promise是js处理异步操作的重要工具,它有效解决了异步回调地狱的问题。通过Promise,我们能够更清晰、简洁地处理异步任务,实现代码的链式调用。下面,我们将逐步深入探讨Promise及其API源码的实现思考过程。

    一、Promise与then方法的实现

    Promise有三个状态:pending(进行中)、fulfilled(已完成)和rejected(已失败),并且状态一旦改变,就不会再变动。基于这些特性,我们来实现Promise的基本功能。

    const PENDING = \'pending\';
    const FULFILLED = \'fulfilled\';
    const REJECTED =\'rejected\';
    
    class myPromise {
        constructor(executor) {
            this.status = PENDING;
            this.value = undefined;
            this.reason = undefined;
            // 存储then方法中成功回调函数的数组,初始注释掉,后续根据需求启用
            // this.onFulfilledCbs = [];
            // 存储then方法中失败回调函数的数组,初始注释掉,后续根据需求启用
            // this.onRejectedCbs = [];
    
            const resolve = (value) => {
                if (this.status === PENDING) {
                    this.status = FULFILLED;
                    this.value = value;
                    // 当状态变为已完成时,执行存储的成功回调函数,初始注释掉,后续根据需求启用
                    // this.onFulfilledCbs.forEach(cb => cb(value));
                }
            };
    
            const reject = (reason) => {
                if (this.status === PENDING) {
                    this.status = REJECTED;
                    this.reason = reason;
                    // 当状态变为已失败时,执行存储的失败回调函数,初始注释掉,后续根据需求启用
                    // this.onRejectedCbs.forEach(cb => cb(reason));
                }
            };
    
            // 执行传入的executor函数,并传递resolve和reject函数
            executor(resolve, reject);
        }
    
        then(onFulfilled, onRejected) {
            return new myPromise((resolve, reject) => {
                let result = undefined;
                if (this.status === FULFILLED) {
                    result = onFulfilled(this.value);
                    resolve(result);
                }
                if (this.status === REJECTED) {
                    result = onRejected(this.reason);
                    reject(result);
                }
                // 如果当前状态还是pending,说明异步操作还未完成,需要存储回调函数,初始注释掉,后续根据需求启用
                // if (this.status === PENDING) {
                //     this.onFulfilledCbs.push(onFulfilled);
                //     this.onRejectedCbs.push(onRejected);
                // }
            });
        }
    }
    
    // 测试示例
    new myPromise((resolve, reject) => {
        // setTimeout(() => {
            resolve(111);
        // }, 1000);
    }).then(res => {
        console.log(\'res\', res);
    });
    

    上述代码初步实现了Promise的链式调用。不过,resolve接收的参数实际上有4种情况,目前代码只处理了基础值这一种。resolve的参数还可能是promisethenable对象或者 ,并且resolve出的值不能是promise自身,否则会导致无限循环引用。为了兼容这些情况,我们进一步完善代码,并使用setTimeout模拟异步操作:

    // promise有三种状态,分别是pending、FULFILLED 、rejected,pending是初始状态,FULFILLED 是成功状态,rejected是失败状态
    // 状态一旦改变,不会再变
    const PENDING = \"pending\";
    const FULFILLED = \"FULFILLED \";
    const REJECTED = \"rejected\";
    
    class Promise1 {
        constructor(excutor) {
            // 实际上resolve,reject这两个函数不是外部传来的,外部只是调用内部的方法并传入值
            this.status = PENDING;
            this.value = undefined;
            this.error = undefined;
            // 存储then方法中onFULFILLED的回调函数
            this.onFulfilledCallbacks = [];
            // 存储then方法中onRejected的回调函数
            this.onRejectedCallbacks = [];
    
            const resolve = (value) => {
                if (this.status === PENDING) {
                    this.status = FULFILLED;
                    this.value = value;
                    this.onFulfilledCallbacks.forEach((callback) => callback());
                }
            };
    
            const reject = (error) => {
                if (this.status === PENDING) {
                    this.status = REJECTED;
                    this.error = error;
                    this.onRejectedCallbacks.forEach((callback) => callback());
                }
            };
    
            try {
                excutor(resolve, reject);
            } catch (error) {
                reject(error);
            }
        }
    
        then(onFulfilled, onRejected) {
            // 处理onFULFILLED不是函数的情况,如果不是函数,就返回传入的值
            onFulfilled = typeof onFulfilled === \"function\"? onFulfilled : (value) => value;
            // 处理onRejected不是函数的情况,如果不是函数,就抛出错误
            onRejected = typeof onRejected === \"function\"? onRejected : (error) => {
                throw error;
            };
    
            // then最终还是会return一个promise
            const promise = new Promise((resolve, reject) => {
                const handleFulfilled = () => {
                    try {
                        const result = onFulfilled(this.value);
                        resolvePromise(promise, result, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                };
    
                const handleRejected = () => {
                    try {
                        const result = onRejected(this.error);
                        resolvePromise(promise, result, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                };
    
                if (this.status === FULFILLED) {
                    // 这里使用setTimeout模拟promise是异步的
                    setTimeout(handleFulfilled, 0);
                } else if (this.status === REJECTED) {
                    setTimeout(handleRejected, 0);
                } else {
                    this.onFulfilledCallbacks.push(() => setTimeout(handleFulfilled, 0));
                    this.onRejectedCallbacks.push(() => setTimeout(handleRejected, 0));
                }
            });
    
            return promise;
        }
    }
    
    function resolvePromise(promise, result, resolve, reject) {
        // 如果promise和result是同一个对象,则抛出TypeError
        if (promise === result) {
            return reject(new TypeError(\"Chaining cycle detected for promise\"));
        }
        // 如果result是thenable对象
        if (result && (typeof result === \"object\" || typeof result === \"function\")) {
            try {
                const then = result.then;
                if (typeof then === \"function\") {
                    // then就是接收两个参数:resolve或reject,然后出结果的函数,直接执行它,但注意this指向,并传参
                    then.call(
                        this,
                        (value) => {
                            resolvePromise(promise, value, resolve, reject);
                        },
                        (reason) => reject(reason)
                    );
                } else {
                    resolve(result);
                }
            } catch (error) {
                reject(error);
            }
        } else {
            // 否则直接调用resolve
            resolve(result);
        }
    }
    

    在这段代码中,resolvePromise函数用于处理resolve参数的各种情况,确保代码的健壮性。

    二、catch方法的实现

    catch方法用于捕获Promise中的错误,它实际上等同于then方法中的第二个参数。因此,我们可以通过调用then方法,并将catch中的回调函数传递给then的第二个参数来实现catch方法:

    // 声明在Promise类中
    catch(cb) {
        return this.then(_, cb);
    }
    

    三、finally方法的实现

    finally方法无论Promise成功还是失败都会执行。我们可以利用then方法来实现finally,无论成功或失败,都通过resolve返回一个promise,这样catch后面也能继续进行链式调用:

    // 声明在Promise类中
    finally(cb) {
        return this.then(
            value => Promise1.resolve(cb()).then(() => value),
            reason => Promise1.resolve(cb()).then(() => reason)
        );
    }
    

    四、Promise类方法的实现

    (一)resolve方法

    Promise.resolve(value) 等同于 new Promise((resolve) => { resolve(value) })。在实现时,我们需要进行判断,如果传入的值本身就是Promise实例,直接返回该实例;否则,创建并返回一个新的Promise实例:

    static resolve(value) {
        if (value instanceof Promise1) {
            return value;
        }
        return new Promise1(() => resolve(value));
    }
    

    (二)reject方法

    reject方法与resolve方法类似,Promise.reject(\'err\') 等同于 new Promise1((_, reject) => reject(\'err\')),实现代码如下:

    static reject(reason) {
        return new Promise1((_, reject) => reject(reason));
    }
    

    (三)race方法

    race方法用于处理多个Promise实例,当其中一个Promise最先执行完毕时,整个操作的结果就是这个最先完成的Promise的状态。它接收一个数组作为参数,我们遍历这个数组,通过Promise.resolve包装每个Promise实例,并在then回调中处理结果:

    static race(arr) {
        return new Promise1((resolve, reject) => {
            arr.forEach(pro => {
                Promise1.resolve(pro).then((value) => {
                    resolve(value);
                }, reason => {
                    reject(reason);
                });
            });
        });
    }
    

    (四)all方法

    all方法要求所有Promise实例都成功,整个操作才成功;只要有一个失败,结果就是失败。实现时,我们需要计算成功的次数,当成功的个数等于数组长度时,resolve结果数组:

    static all(arr) {
        return new Promise1((resolve, reject) => {
            let res = [];
            let completeCount = 0;
            if (arr.length === 0) {
                resolve(res);
                return;
            }
            arr.forEach((pro) => {
                Promise1.resolve(pro).then(
                    (value) => {
                        res[completeCount] = value;
                        completeCount++;
                        if (completeCount === arr.length) {
                            resolve(res);
                        }
                    },
                    (err) => {
                        reject(err);
                    }
                );
            });
        });
    }
    

    (五)allSettled方法

    allSettled方法不管Promise实例是成功还是失败,都会返回结果。结果数组中的每个对象包含status(表示状态,fulfilled为成功,rejected为失败)和对应的结果值。当所有Promise实例都执行完毕后,resolve结果数组:

    static allSettled(promises) {
        return new Promise1((resolve, reject) => {
            const results = [];
            let completedCount = 0;
            if (promises.length === 0) {
                resolve(results);
                return;
            }
            promises.forEach((promise, index) => {
                Promise1.resolve(promise).then(
                    (value) => {
                        results[index] = {
                            status: \"fulfilled\",
                            value,
                        };
                        completedCount++;
                        if (completedCount === promises.length) {
                            resolve(results);
                        }
                    },
                    (reason) => {
                        results[index] = {
                            status: \"rejected\",
                            reason,
                        };
                        completedCount++;
                        if (completedCount === promises.length) {
                            resolve(results);
                        }
                    }
                );
            });
        });
    }
    

    最后,给大家留一个作业:实现any方法。这个方法要求只要有一个Promise实例成功,包装实例就返回fulfilled状态;只有当所有Promise实例都失败时,结果才是rejected状态。希望大家通过实践,进一步加深对Promise的理解。

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/6936.html

管理员

相关推荐
2025-08-06

文章目录 一、Promise基础回顾 二、Promise 与 axios 结合使用场景及方法 (一)直接返回 axios …

269
2025-08-06

文章目录 一、模块初始化时的内部机制 二、常见导出写法的差异分析 (一)写法一:module.exports…

107
2025-08-06

文章目录 一、ResizeObserver详解 (一)ResizeObserver是什么 (二)ResizeObserver的基本用法 …

683
2025-08-06

文章目录 一、前期准备工作 (一)下载相关文件 (二)安装必要工具 二、处理扣子空间生成的文件…

338
2025-08-06

文章目录 一、官方文档 二、自动解包的数据类型 ref对象:无需.value即可访问 reactive对象:保持…

371
2025-08-06

文章目录 一、Hooks的工作原理 二、在if语句中使用Hook会出什么岔子? 三、React官方的Hook使用规…

843
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号