自己动手用js写一个Promise对象

本文探讨如何手工实现一个JavaScript Promise对象。重点在于理解Promise的工作原理,特别是它如何与事件循环(eventLoop)交互。虽然文章提及在实现过程中将回调放入了宏队列,但作者期待了解如何正确放入微队列,欢迎读者交流讨论。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

eventLoop那里Promise对象的产生的回调应该放到微队列中,但是不知道该怎么实现,所以放到了宏队列中(有大佬知道的话劳请告知,哪里看不懂可以把问题放到评论区或者私信我,看到就回)


const MyPromise = (() => {

const PENDING = 'pending',
    RESOLVED = 'resolved',
    REJECTED = 'rejected',
    MyPromiseStatus = Symbol('MyPromiseStatus'),
    MyPromiseValue = Symbol('MyPromiseValue'),
    changeStatus = Symbol('changeStatus'),
    thenables = Symbol('thenable'),  //thenable 业队列
    catchables = Symbol('catchable'),   /catchable作业队列
    subsequentHandle = Symbol('subsequentHandle')//后续处理函数的封装
    linkPromise = Symbol('linkPromise');
return class {
    /**
     * 将Promise从未决状态推向已决状态时,改变状的函数
     * @param {*} data 状态数据
     * @param {*} immediatelyStatus 推向已决状态应该所处的状态 
     * @param {*} targetStatus 将要推向的状态
     * @returns 
     */
    [changeStatus](value, targetStatus, queue) {
        // 如果状态是pending
        if (this[MyPromiseStatus] !== PENDING) {
            return;
        }
        // 状态是已决态
        this[MyPromiseStatus] = targetStatus;
        this[MyPromiseValue] = value;
        // 遍历执行作业队列中的处理函数
        queue.forEach(handle => handle(thi[MyPromiseValue]))
    }
    constructor(untreated) {
        // untreated表示未决阶段的处理函数
        this[MyPromiseStatus] = PENDING;
        this[MyPromiseValue] = undefined;
        this[thenables] = [];
        this[catchables] = [];
        const resolve = (data) => {
            this[changeStatus](data, RESOLVED,this[thenables]);
        }
        const reject = (reason) => {
            this[changeStatus](reason, REJECTED,this[catchables]);
            // 拒绝的话打印错误消息,Promise直接出的错误   
            // console.error(new Error(reason));
        }
        // 捕获到错误后将错误数据传递作为rejecte的状态数据
        try {
            // 这里untreated是一个形参,他是传一带有两个函数作为参
            //数的函数,第一个参数是resolve, 第个参数是reject,这里将他写全调用即可
            untreated(resolve, reject);
        }
        catch (err) {
            // 捕获到初始化函数执行中的错误后将误信息设置为状态数据,并改变状态
            this[MyPromiseValue] = err;
            this[MyPromiseStatus] = REJECTED;
        }
    }
    /**
     * 针对then和catch写的封装函数 handlerthenable或者catchable
     * @param {*} handler catchable或者thenable理函数
     * @param {*} immediatelyStatus 
     * @param {*} queue 
     */
    [subsequentHandle](handler,immediatelyStatus, queue) {
        if (typeof handler !== 'function') {
            return;
        }
        if (this[MyPromiseStatus] ===immediatelyStatus) {
            // 直接执行函数
            setTimeout(() => {
                handler(this[MyPromiseValue]);
                //注意这里函数如果直接执行的话,
                //会将这个参数传递给立即执行函数data
            }, 0)
        } else {
            queue.push(handler);    
         //注意这里的函数如果不立即执行的话,会改变状态那里遍历执行
        }
    }
    /**
     * 返回一个后续处理函数返回的Promise对象
     * @param {*} thenable 
     * @param {*} catchable 
     * @returns 
     */
    [linkPromise](thenable, catchable) {
        /**
         * 
         * @param {*} data 改变状态函数那里立即行传进来的实参
         * @param {*} handle 当前Promise对象的后处理函数
         * @param {*} resolve 返回的新的Promiseresolve
         * @param {*} reject 返回的新的Promisereject
         */
        function exec(data, handle, resolve,reject) {
            try {
                // handle是当前Promise 后续处理数
                const result = handle(data);    
                //立即执行的话需要知道当前的data,
                //这个data就是异步立即执行那里传来的实参
                if (result instanceof MyPromise) {
                    result.then(data => {
                        resolve(data);
                    })
                } else {
                    resolve(result);
                }
            } catch (error) {
                reject(error)
            }
        }
        return new MyPromise((resolve, reject) =>{
            // 返回的新的promise对象是当thenale数执行后返回,并且该Promise的状态
            //数据为thenable函数的返回值,也就是什么时候返回新的对象,是当
            //catchable执行之后在返回
            this[subsequentHandle]((data) => {
         // 该promise对象没有添加thenable 函数,回的全新的Promise对象的状态数据应
         //该是该promise对象的状态数据,而且此时态(该promise状态已经是resolved
         //了,返回的全新的Promise对象的状态应该是thenable)应该改变
                if (typeof thenable !=='function') {
                    resolve(data);//调用这个函数时候状态会自动更改
                    return;//防止执行exec函数,致状态无法改变
                }
                exec(data, thenable, resolve,reject);
            }, RESOLVED, this[thenables]);
            this[subsequentHandle]((reason) => {
                if (typeof catchable !=='function') {
                    reject(reason);//调用这个函的时候状态会自动更改
                    return;//防止执行exec函数,致状态无法改变
                }
                exec(reason, catchable, resolve,reject);
            }, REJECTED, this[catchables]);
        })
    }
    then(thenable, catchable) {
        //  这里面的代码是 异步代码,如果这里Promie状态是RESOLVED,
        //立即执行,如果是pending,则加入到queue中
        // this[subsequentHandle](thenable,RESOLVED, this[thenables]);
        // if (typeof catchable === 'function') {
        //     this[subsequentHandle](catchable,REJECTED, this[catchables]);
        // }
        return this[linkPromise](thenable,catchable);
    }
    catch(catchable) {
        // this[subsequentHandle](catchable,REJECTED, this[catchables]);
        return this[linkPromise](undefined,catchable);
    }
    static all(pros) {
        return new MyPromise((resolve, reject) =>{
            try {
                const results = pros.map(p => {
                    const obj = {
                        result: undefined,
                        isResolve: false
                    }
                    p.then(data => {
                        obj.result = data;
                        obj.isResolve = true;
                        const unResolve =results.filter((item) =>!item.isResolve);
                        if (unResolve.length ===0) {
                            resolve(results.map(item => item.result);
                        }
                    }, reason => {
                        reject(reason);
                    })
                    return obj;
                })
            } catch (error) {
                reject(error);
            }
        })
    }
    static race(pros) {
        return new MyPromise((resolve, reject) =>{
            try {
                pros.forEach((item) => {
                    // item是一个Promise,其中有个item resolve,
                    item.then(data => {
                        resolve(data);
                    }, reason => {
                        reject(reason);
                    })
                })
            } catch (error) {
                reject(error);
            }
        })
    }
    static resolve(data) {
        return new MyPromise((resolve) => {
            resolve(data);
        })
    }
    static reject(reason) {
        return new MyPromise((resolve, reject) =>{
            reject(reason);
        })
    }
}
})()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值