当前位置: 首页 > article >正文

19-简单理解JavaScript中的Promise:手写Promise实现

笔记+分享

在现代JavaScript开发中,异步编程是不可避免的一部分。为了更好地处理异步操作,ES6引入了Promise。Promise使得异步代码更具可读性和可维护性。通过手写一个完整的Promise实现,可以帮助你更深入地理解其工作原理。本文将详细介绍Promise的概念、用法及其在实际开发中的应用,并提供一个手写的Promise实现。

什么是Promise?

Promise是JavaScript中的一种对象,用于表示一个异步操作的最终完成(或失败)及其结果值。它有三种状态:

  1. Pending(待定):初始状态,既没有被兑现,也没有被拒绝。
  2. Fulfilled(已兑现):操作成功完成,并返回一个值。
  3. Rejected(已拒绝):操作失败,并返回一个原因。

手写Promise实现

我们将通过构建一个简化版的Promise实现来更好地理解其工作原理。

class MyPromise {
    constructor(executor) {
        this.state = 'pending'; // 初始状态
        this.value = undefined; // 成功时的值
        this.reason = undefined; // 失败时的原因
        this.onFulfilledCallbacks = []; // 成功的回调函数数组
        this.onRejectedCallbacks = []; // 失败的回调函数数组

        const resolve = (value) => {
            if (this.state === 'pending') {
                this.state = 'fulfilled';
                this.value = value;
                this.onFulfilledCallbacks.forEach(fn => fn());
            }
        };

        const reject = (reason) => {
            if (this.state === 'pending') {
                this.state = 'rejected';
                this.reason = reason;
                this.onRejectedCallbacks.forEach(fn => fn());
            }
        };

        try {
            executor(resolve, reject);
        } catch (error) {
            reject(error);
        }
    }

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

        let promise2 = new MyPromise((resolve, reject) => {
            if (this.state === 'fulfilled') {
                setTimeout(() => {
                    try {
                        let x = onFulfilled(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                }, 0);
            }

            if (this.state === 'rejected') {
                setTimeout(() => {
                    try {
                        let x = onRejected(this.reason);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                }, 0);
            }

            if (this.state === 'pending') {
                this.onFulfilledCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onFulfilled(this.value);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (error) {
                            reject(error);
                        }
                    }, 0);
                });

                this.onRejectedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onRejected(this.reason);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (error) {
                            reject(error);
                        }
                    }, 0);
                });
            }
        });

        return promise2;
    }

    catch(onRejected) {
        return this.then(null, onRejected);
    }

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

    static reject(reason) {
        return new MyPromise((resolve, reject) => {
            reject(reason);
        });
    }

    static all(promises) {
        return new MyPromise((resolve, reject) => {
            let results = [];
            let completed = 0;

            const processResult = (index, value) => {
                results[index] = value;
                if (++completed === promises.length) {
                    resolve(results);
                }
            };

            promises.forEach((promise, index) => {
                MyPromise.resolve(promise).then(value => {
                    processResult(index, value);
                }, reject);
            });
        });
    }

    static race(promises) {
        return new MyPromise((resolve, reject) => {
            promises.forEach(promise => {
                MyPromise.resolve(promise).then(resolve, reject);
            });
        });
    }
}

function resolvePromise(promise2, x, resolve, reject) {
    if (promise2 === x) {
        return reject(new TypeError('Chaining cycle detected for promise'));
    }

    let called = false;

    if (x && (typeof x === 'object' || typeof x === 'function')) {
        try {
            let then = x.then;
            if (typeof then === 'function') {
                then.call(x, y => {
                    if (called) return;
                    called = true;
                    resolvePromise(promise2, y, resolve, reject);
                }, reason => {
                    if (called) return;
                    called = true;
                    reject(reason);
                });
            } else {
                resolve(x);
            }
        } catch (error) {
            if (called) return;
            called = true;
            reject(error);
        }
    } else {
        resolve(x);
    }
}

关键点解释

  1. 状态管理:Promise有三种状态:pendingfulfilledrejected。通过state变量来管理当前Promise的状态。
  2. 回调队列:使用两个数组onFulfilledCallbacksonRejectedCallbacks来存储在pending状态时注册的回调函数。
  3. resolve和rejectresolve函数将Promise状态从pending变为fulfilled,并执行所有成功回调;reject函数将Promise状态从pending变为rejected,并执行所有失败回调。
  4. then方法then方法返回一个新的Promise,并根据当前Promise的状态决定如何处理回调函数。
  5. resolvePromise函数:这个函数用来处理then方法中的链式调用,确保Promise的规范执行,防止循环引用等问题。

用法示例

const p1 = new MyPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('成功');
    }, 1000);
});

p1.then(value => {
    console.log(value); // 输出 "成功"
    return new MyPromise((resolve, reject) => {
        setTimeout(() => {
            resolve('链式调用成功');
        }, 1000);
    });
}).then(value => {
    console.log(value); // 输出 "链式调用成功"
}).catch(error => {
    console.error(error);
});

通过这个手写的Promise实现,你可以更好地理解Promise的内部工作机制,并在实际开发中灵活运用Promise来处理异步操作。希望这篇博客能帮助你深入理解JavaScript中的Promise。


http://www.kler.cn/a/397926.html

相关文章:

  • 从零到一:利用 AI 开发 iOS App 《震感》的编程之旅
  • js导入导出
  • 2024-11-16 串的存储结构
  • 整数唯一分解定理
  • 实验8.1 无失真信源编码的实现
  • 逆向攻防世界CTF系列37-crackme
  • Redis高可用-主从复制
  • 无人机吊舱基础——CKESC电调小课堂09
  • 永夜星河主题特效2(星河背景 + 闪烁文字+点击星星 + 文字弹出特效)
  • skywalking各项指标说明
  • Robot | 用 RDK 做一个小型机器人(更新中)
  • 222. 完全二叉树的节点个数【 力扣(LeetCode) 】
  • uniapp 跨域前端代理
  • FPGA 第8讲 简单组合逻辑--半加器
  • uni-app快速入门(三)--UniApp生命周期
  • java导出pdf
  • 后台管理系统(开箱即用)
  • 20241116下载中科创达的TurboX D660核心板的Android11的SDK的详细LOG
  • 前端第一天 鸿蒙实训第19天 前端篇
  • DAY29|贪心算法Part03|LeetCode:134. 加油站、135. 分发糖果、860.柠檬水找零、406.根据身高重建队列
  • 论文 | The Capacity for Moral Self-Correction in LargeLanguage Models
  • 蓝队基础2 -- 外部威胁与攻击面
  • 报错ImportError: Pandas requires version ‘3.0.7‘ or newer of ‘openpyxl‘
  • pom中无法下载下来的类外部引用只给一个jar的时候
  • ArkUI---常用组件---切换按钮 (Toggle)
  • 重置docker版本的octoprint管理员账号密码