凌的博客

您现在的位置是: 首页 > 前端学习 > Js > 

Js

自定义Promise对象案例

2023-05-09 Js 897
window.onload = function () {

    class Promise {


        // 定义三个静态属性
        static PENDING = 'pending';
        static FULFILLED = 'fulfilled';
        static REJECTED = 'rejected';

        // 定义构造函数
        constructor(executor) {
            // 初始化状态为pending
            this.state = 'pending';
            // 初始化成功值和失败原因
            this.value = undefined;
            this.reason = undefined;

            // 初始化回调函数数组
            this.onResolvedCallbacks = [];
            this.onRejectedCallbacks = [];

            // 定义一个resolve函数,用于改变状态和传递成功值
            let resolve = (value) => {
                // 只有在pending状态下才能改变状态
                if (this.state === 'pending') {
                    // 改变状态为fulfilled
                    this.state = 'fulfilled';
                    // 保存成功值
                    this.value = value;
                    // 遍历并执行成功回调数组中的函数
                    this.onResolvedCallbacks.forEach(fn => fn());
                }
            };
            // 定义一个reject函数,用于改变状态和传递失败原因
            let reject = (reason) => {
                // 只有在pending状态下才能改变状态
                if (this.state === 'pending') {
                    // 改变状态为rejected
                    this.state = 'rejected';
                    // 保存失败原因
                    this.reason = reason;
                    // 遍历并执行失败回调数组中的函数
                    this.onRejectedCallbacks.forEach(fn => fn());
                }
            };
            // 执行执行器函数,并传入resolve和reject函数
            try {
                executor(resolve, reject);
            } catch (e) {
                // 如果执行器函数抛出异常,直接调用reject函数
                reject(e);
            }

        }

        // 定义一个then方法,接收两个参数,分别是成功回调和失败回调
        then(onFulfilled, onRejected) {
            // 如果参数不是函数,就给一个默认函数,实现透传效果
            onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
            onRejected = typeof onRejected === 'function' ? onRejected : reason => {
                throw reason
            };
            // 返回一个新的Promise对象,用于实现链式调用
            let promise2 = new Promise((resolve, reject) => {
                // 如果当前状态是fulfilled,就异步执行成功回调,并传入成功值
                if (this.state === 'fulfilled') {
                    setTimeout(() => {
                        try {
                            // 获取成功回调的返回值
                            let x = onFulfilled(this.value);
                            // 调用resolvePromise函数,处理返回值和新Promise对象的关系
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            // 如果成功回调抛出异常,直接调用reject函数
                            reject(e);
                        }
                    }, 0);
                }
                // 如果当前状态是rejected,就异步执行失败回调,并传入失败原因
                if (this.state === 'rejected') {
                    setTimeout(() => {
                        try {
                            // 获取失败回调的返回值
                            let x = onRejected(this.reason);
                            // 调用resolvePromise函数,处理返回值和新Promise对象的关系
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            // 如果失败回调抛出异常,直接调用reject函数
                            reject(e);
                        }
                    }, 0);
                }
                // 如果当前状态是pending,就将成功回调和失败回调存入对应的数组中,等待状态改变时再执行
                if (this.state === 'pending') {
                    this.onResolvedCallbacks.push(() => {
                        setTimeout(() => {
                            try {
                                let x = onFulfilled(this.value);
                                resolvePromise(promise2, x, resolve, reject);
                            } catch (e) {
                                reject(e);
                            }
                        }, 0);
                    });
                    this.onRejectedCallbacks.push(() => {
                        setTimeout(() => {
                            try {
                                let x = onRejected(this.reason);
                                resolvePromise(promise2, x, resolve, reject);
                            } catch (e) {
                                reject(e);
                            }
                        }, 0);
                    });
                }
            });
            // 返回新的Promise对象
            return promise2;
        }
    }

    // 定义一个resolvePromise函数,用于处理成功回调或失败回调的返回值和新Promise对象的关系
    function resolvePromise(promise2, x, resolve, reject) {
        // 如果返回值和新Promise对象是同一个对象,就抛出类型错误
        if (promise2 === x) {
            return reject(new TypeError('Chaining cycle detected for promise'));
        }
        // 定义一个标志,用于防止多次调用resolve或reject函数
        let called;
        // 如果返回值是一个对象或函数,就认为它是一个thenable对象,有可能是一个Promise对象
        if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
            try {
                // 获取then属性
                let then = x.then;
                // 如果then属性是一个函数,就认为它是一个Promise对象,就以它的状态作为新Promise对象的状态
                if (typeof then === 'function') {
                    // 调用then方法,并传入两个函数作为参数
                    then.call(x, y => {
                        // 如果已经调用过resolve或reject函数,就直接返回
                        if (called) return;
                        // 否则将标志置为true
                        called = true;
                        // 递归调用resolvePromise函数,处理y值和新Promise对象的关系
                        resolvePromise(promise2, y, resolve, reject);
                    }, r => {
                        // 如果已经调用过resolve或reject函数,就直接返回
                        if (called) return;
                        // 否则将标志置为true
                        called = true;
                        // 直接调用reject函数,并传入r值
                        reject(r);
                    });
                } else {
                    // 如果then属性不是一个函数,就直接调用resolve函数,并传入x值
                    resolve(x);
                }
            } catch (e) {
                // 如果在获取或调用then属性时抛出异常,就直接调用reject函数,并传入e值
                if (called) return;
                called = true;
                reject(e);
            }
        } else {
            // 如果返回值不是一个对象或函数,就直接调用resolve函数,并传入x值
            resolve(x);
        }
    }


    // 使用上面的Promise实现 延迟x秒打印hello world
    function delay(time,msg) {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(msg);
            }, time);
        });
    }

    delay(1000,'hello world').then((msg) => {
        console.log(msg);
    });

}


文章评论

0条评论