搞懂promise【4】模拟源码,淦

状态数据

const MyPromise = (() => {

    const PENDING = 'pending', //状态变量
        RESOLVED = 'resolved',
        REJECTED = 'rejected',
        // 符号变量外面的访问不到
        promiseStatus = Symbol('PromiseStatus'), //promise的状态
        promiseValue = Symbol('promiseValue'), // promise的状态数据
        changeStatus = Symbol('changeStatus'); //该变promise的状态

        return class MyPromise {

            /**
             * 改变状态的函数
             * @param {*} data 状态数据
             * @param {*} status 状态
             */
            [changeStatus](data, status) {
                //状态不可逆或者说只有在pending状态下才能推向resolved或rejected
                if (this[promiseStatus] !== PENDING) {
                    // 如果不是pending直接结束
                    return;
                }
                // 是pending才推向后续状态
                this[promiseStatus] = status;
                this[promiseValue] = data;
            }

            /**
             * 
             * @param {*} executor 未决阶段(pending状态)下的处理函数
             */
            constructor(executor) {
                //刚开始为pending
                this[promiseStatus] = PENDING;
                //刚开始状态数据为undefined
                this[promiseValue] = undefined;

                /**
                 * executor 为new Promise(executor)传递进来的函数
                 *  1.要同步执行,所在构造器函数里面要调用一次。
                 *  2.executor有两个参数,resolve和reject也是函数,所以这个要写两个函数
                 */
                /**
                 * resolve有改变状态的能力
                 * 由于要改变状态和状态数据,所以要用this,
                 * 但是外面是直接调用resolve,this指向全局
                 * 所以这里用箭头函数方便点
                 * 然后分析reject函数也是如此,所以写个函数
                 * @param {*} data 状态数据
                 */
                const resolve = (data) => {
                    this[changeStatus](data, RESOLVED);
                };

                /**
                 * reject也有改变状态的能力
                 * @param {*} error 状态数据
                 */
                const reject = (error) => {
                    this[changeStatus](error, REJECTED);
                }
                /**
                 * 调用executor函数,执行同步代码
                 * 如果这里抛出错误就要推向rejected状态
                 * 所以要捕获错误,然后推向rejected
                 * */
                try {
                    executor(resolve, reject);
                } catch (err) {
                    reject(err);
                }
            }
        }
})();
  • 测试
<script src="./MyPromise.js"></script>
    <script>
        const pro = new MyPromise((resolve,reject)=>{
            console.log('111');
            // resolve('状态数据');
            // setTimeout(()=>{
            //     resolve('状态数据');
            // },3000)
                throw new Error('reject')
        });
        console.log(pro);
    </script>

在这里插入图片描述

后续处理

  • then,catch函数
const MyPromise = (() => {
    const PENDING = "pending",
        RESOLVED = "resolved",
        REJECTED = "rejected",
        PromiveValue = Symbol("PromiseValue"), //状态数据
        PromiseStatus = Symbol("PromiseStatus"),
        thenables = Symbol("thenables"), //thenable
        catchables = Symbol("catchbles"), //catchables
        changeStatus = Symbol("changeStatus"),//当前状态
        settleHandle = Symbol("settleHandle"), //后续处理的通用函数
        linkPromise = Symbol("linkPromise");  //创建串联的Promise

    return class MyPromise {

        /**
         * 改变当前Promise的状态
         * @param {*} newStatus 
         * @param {*} newValue 
         * @param {*} queue 执行的作业队列
         */
        [changeStatus](newStatus, newValue, queue) {
            if (this[PromiseStatus] !== PENDING) {
                //状态无法变更
                return;
            }
            this[PromiseStatus] = newStatus;
            this[PromiveValue] = newValue;
            //执行相应队列中的函数
            queue.forEach(handler => handler(newValue));
        }

        /**
         * 
         * @param {*} executor 未决阶段(pending状态)下的处理函数
         */
        constructor(executor) {
            this[PromiseStatus] = PENDING;
            this[PromiveValue] = undefined;
            this[thenables] = []; //后续处理函数的数组 -> resolved
            this[catchables] = []; //后续处理函数的数组 -> rejected

            const resolve = data => {
                this[changeStatus](RESOLVED, data, this[thenables]);
            }

            const reject = reason => {
                this[changeStatus](REJECTED, reason, this[catchables]);
            }
            try {
                executor(resolve, reject)
            }
            catch (err) {
                reject(err);
            }
        }

        /**
         * 处理 后续处理函数
         * @param {*} handler 后续处理函数
         * @param {*} immediatelyStatus 需要立即执行的状态
         * @param {*} queue 作业队列
         */
        [settleHandle](handler, immediatelyStatus, queue) {
            if (typeof handler !== "function") {
                return;
            }
            if (this[PromiseStatus] === immediatelyStatus) {
                //直接运行
                setTimeout(() => {
                    handler(this[PromiveValue]);
                }, 0);
            }
            else {
                queue.push(handler);
            }
        }

        [linkPromise](thenalbe, catchable) {
            function exec(data, handler, resolve, reject) {
                try {
                    const result = handler(data); //得到当前Promise的处理结果
                    if (result instanceof MyPromise) {
                        result.then(d => {
                            resolve(d)
                        }, err => {
                            reject(err);
                        })
                    }
                    else {
                        resolve(result);
                    }
                }
                catch (err) {
                    reject(err);
                }
            }

            return new MyPromise((resolve, reject) => {
                this[settleHandle](data => {
                    exec(data, thenalbe, resolve, reject);
                }, RESOLVED, this[thenables])

                this[settleHandle](reason => {
                    exec(reason, catchable, resolve, reject);
                }, REJECTED, this[catchables])
            })
        }

        then(thenable, catchable) {
            return this[linkPromise](thenable, catchable);
        }

        catch(catchable) {

            return this[linkPromise](undefined, catchable);
        }


        static all(proms) {
            return new Promise((resolve, reject) => {
                const results = proms.map(p => {
                    const obj = {
                        result: undefined,
                        isResolved: false
                    }
                    p.then(data => {
                        obj.result = data;
                        obj.isResolved = true;
                        //判断是否所有的全部完成
                        const unResolved = results.filter(r => !r.isResolved)
                        if (unResolved.length === 0) {
                            //全部完成
                            resolve(results.map(r => r.result));
                        }
                    }, reason => {
                        reject(reason);
                    })
                    return obj;
                })
            })
        }

        static race(proms) {
            return new Promise((resolve, reject) => {
                proms.forEach(p => {
                    p.then(data => {
                        resolve(data);
                    }, err => {
                        reject(err);
                    })
                })
            })
        }

        static resolve(data) {
            if (data instanceof MyPromise) {
                return data;
            }
            else {
                return new MyPromise(resolve => {
                    resolve(data);
                })
            }
        }

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

promise 的串联

const MyPromise = (() => {

    const PENDING = 'pending', //状态变量
        RESOLVED = 'resolved',
        REJECTED = 'rejected',
        // 符号变量外面的访问不到
        promiseStatus = Symbol('PromisrStatus'), //promise的状态
        promiseValue = Symbol('promiseValue'), // promise的状态数据
        changeStatus = Symbol('changeStatus'), //该变promise的状态
        thenables = Symbol('thenables'), //thenables作业队列
        catchables = Symbol('catchables'), //catchables作业队列
        settleHandle = Symbol('settleHandle'), //后续处理函数
        linkPromise = Symbol('linkPromise'); //返回的promise

    return class MyPromise {
        /**
         * 
         * @param {*} executor 未决阶段(pending状态)下的处理函数
         */
        constructor(executor) {
            //刚开始为pending
            this[promiseStatus] = PENDING;
            //刚开始状态数据为undefined
            this[promiseValue] = undefined;
            //初始化作业队列
            this[thenables] = [];
            this[catchables] = [];
            /**
             * executor 为new Promise(executor)传递进来的函数
             *  1.要同步执行,所在构造器函数里面要调用一次。
             *  2.executor有两个参数,resolve和reject也是函数,所以这个要写两个函数
             */
            /**
             * resolve有改变状态的能力
             * 由于要改变状态和状态数据,所以要用this,
             * 但是外面是直接调用resolve,this指向全局
             * 所以这里用箭头函数方便点
             * 然后分析reject函数也是如此,所以写个函数
             * @param {*} data 状态数据
             */
            const resolve = (data) => {
                this[changeStatus](data, RESOLVED, this[thenables]);
            };

            /**
             * reject也有改变状态的能力
             * @param {*} error 状态数据
             */
            const reject = (error) => {
                this[changeStatus](error, REJECTED, this[catchables]);
            }
            /**
             * 调用executor函数,执行同步代码
             * 如果这里抛出错误就要推向rejected状态
             * 所以要捕获错误,然后推向rejected
             * */
            try {
                executor(resolve, reject);
            } catch (err) {
                reject(err);
            }
        }
        /**
         * 改变状态的函数
         * @param {*} data 状态数据
         * @param {*} status 状态
         * @param {*} queue 执行的作业队列
         */
        [changeStatus](data, status, queue) {
            //状态不可逆或者说只有在pending状态下才能推向resolved或rejected
            if (this[promiseStatus] !== PENDING) {
                // 如果不是pending直接结束
                return;
            }
            // 是pending才推向后续状态
            this[promiseStatus] = status;
            this[promiseValue] = data;
            //状态改变了 要运行作业队列
            queue.forEach((handle) => handle(data));
        }

        /**
         * 后续处理函数
         * @param {*} handle 后续处理函数
         * @param {*} immediatelyStatus 状态
         * @param {*} queue 作业队列
         */
        [settleHandle](handle, immediatelyStatus, queue) {
            //handle 不是一个函数直接返回
            if (typeof handle !== 'function') {
                return;
            }
            if (this[promiseStatus] === immediatelyStatus) {
                setTimeout(() => {
                    handle(this[promiseValue]);
                })
            } else {
                queue.push(handle);
            }
        }
        [linkPromise](thenable, catchable) {
            return new MyPromise((resolve, reject) => {
                this[settleHandle](data => {
                    try {
                        const result = thenable(data); // 返回的结果 当前promise的处理结果
                        resolve(result); //然后返回的promise推向resolved状态
                    } catch (err) {
                        //出了问题才推向rejected
                        reject(err);
                    }

                }, RESOLVED, this[thenables]);
                this[settleHandle](err => {
                    try {
                        const result = catchable(err); // 返回的结果 当前promise的处理结果
                        resolve(result); //然后返回的promise推向resolved状态
                    } catch (err) {
                        reject(err);
                    }
                }, REJECTED, this[catchables]);
            })
        }

        then(thenable, catchable) {
            //调用then方法传递一个函数,或者两个函数
            //如果状态是resolved那么立即执行
            //如果不是resolved那么就加入到作业队列里面,等到是resolved才执行
            //reject也是同样的处理

            //状态是resolved那么立即执行
            // if (this[promiseStatus] === RESOLVED) {
            //     //由于是异步执行,并且真实的效果是放在微队列里面的,而在浏览器环境中没有办法放入微队列里面,
            //     //所以这里采用setTimeout来模拟,放入到宏任务里面
            //     setTimeout(() => {
            //         //将数据传给他,然后外面调用的函数中的data才有值
            //         thenable(this[promiseValue]);
            //     })
            // } else {
            //     // 不是resolved那么就加入到作业队列里面
            //     this[thenables].push(thenable);
            // }

            // this.catch(catchable);
            // this[settleHandle](thenable, RESOLVED, this[thenables]);
            // this.catch(catchable);

            // 调用then要返回一个promise
            return this[linkPromise](thenable, catchable);
        }
        catch (catchable) {
            // this[settleHandle](catchable, REJECTED, this[catchables]);
            return this[linkPromise](thenable, catchable);
        }
    }
})();

其它api完整的MyPromise

const MyPromise = (() => {

    const PENDING = 'pending', //状态变量
        RESOLVED = 'resolved',
        REJECTED = 'rejected',
        // 符号变量外面的访问不到
        promiseStatus = Symbol('PromisrStatus'), //promise的状态
        promiseValue = Symbol('promiseValue'), // promise的状态数据
        changeStatus = Symbol('changeStatus'), //该变promise的状态
        thenables = Symbol('thenables'), //thenables作业队列
        catchables = Symbol('catchables'), //catchables作业队列
        settleHandle = Symbol('settleHandle'), //后续处理函数
        linkPromise = Symbol('linkPromise'); //返回的promise

    return class MyPromise {
        /**
         * 
         * @param {*} executor 未决阶段(pending状态)下的处理函数
         */
        constructor(executor) {
            //刚开始为pending
            this[promiseStatus] = PENDING;
            //刚开始状态数据为undefined
            this[promiseValue] = undefined;
            //初始化作业队列
            this[thenables] = [];
            this[catchables] = [];
            /**
             * executor 为new Promise(executor)传递进来的函数
             *  1.要同步执行,所在构造器函数里面要调用一次。
             *  2.executor有两个参数,resolve和reject也是函数,所以这个要写两个函数
             */
            /**
             * resolve有改变状态的能力
             * 由于要改变状态和状态数据,所以要用this,
             * 但是外面是直接调用resolve,this指向全局
             * 所以这里用箭头函数方便点
             * 然后分析reject函数也是如此,所以写个函数
             * @param {*} data 状态数据
             */
            const resolve = (data) => {
                this[changeStatus](data, RESOLVED, this[thenables]);
            };

            /**
             * reject也有改变状态的能力
             * @param {*} error 状态数据
             */
            const reject = (error) => {
                this[changeStatus](error, REJECTED, this[catchables]);
            }
            /**
             * 调用executor函数,执行同步代码
             * 如果这里抛出错误就要推向rejected状态
             * 所以要捕获错误,然后推向rejected
             * */
            try {
                executor(resolve, reject);
            } catch (err) {
                reject(err);
            }
        }
        /**
         * 改变状态的函数
         * @param {*} data 状态数据
         * @param {*} status 状态
         * @param {*} queue 执行的作业队列
         */
        [changeStatus](data, status, queue) {
            //状态不可逆或者说只有在pending状态下才能推向resolved或rejected
            if (this[promiseStatus] !== PENDING) {
                // 如果不是pending直接结束
                return;
            }
            // 是pending才推向后续状态
            this[promiseStatus] = status;
            this[promiseValue] = data;
            //状态改变了 要运行作业队列
            queue.forEach((handle) => handle(data));
        }

        /**
         * 后续处理函数
         * @param {*} handle 后续处理函数
         * @param {*} immediatelyStatus 状态
         * @param {*} queue 作业队列
         */
        [settleHandle](handle, immediatelyStatus, queue) {
            //handle 不是一个函数直接返回
            if (typeof handle !== 'function') {
                return;
            }
            if (this[promiseStatus] === immediatelyStatus) {
                setTimeout(() => {
                    handle(this[promiseValue]);
                })
            } else {
                queue.push(handle);
            }
        }
        [linkPromise](thenable, catchable) {
            return new MyPromise((resolve, reject) => {
                this[settleHandle](data => {
                    if (typeof thenable !== 'function') {
                        resolve(data);
                        return;
                    }
                    try {
                        const result = thenable(data); // 返回的结果 当前promise的处理结果
                        if (result instanceof MyPromise) {
                            //返回的是promise
                            result.then(d => {
                                resolve(d);
                            }, err => {
                                reject(err);
                            })
                        } else {
                            resolve(result); //然后返回的promise推向resolved状态
                        }
                    } catch (err) {
                        //出了问题才推向rejected
                        reject(err);
                    }

                }, RESOLVED, this[thenables]);
                this[settleHandle](err => {
                    if (typeof catchable !== 'function') {
                        reject(err);
                        return;
                    }
                    try {
                        const result = catchable(err); // 返回的结果 当前promise的处理结果
                        resolve(result); //然后返回的promise推向resolved状态
                    } catch (err) {
                        reject(err);
                    }
                }, REJECTED, this[catchables]);
            })
        }

        then(thenable, catchable) {
            //调用then方法传递一个函数,或者两个函数
            //如果状态是resolved那么立即执行
            //如果不是resolved那么就加入到作业队列里面,等到是resolved才执行
            //reject也是同样的处理

            //状态是resolved那么立即执行
            // if (this[promiseStatus] === RESOLVED) {
            //     //由于是异步执行,并且真实的效果是放在微队列里面的,而在浏览器环境中没有办法放入微队列里面,
            //     //所以这里采用setTimeout来模拟,放入到宏任务里面
            //     setTimeout(() => {
            //         //将数据传给他,然后外面调用的函数中的data才有值
            //         thenable(this[promiseValue]);
            //     })
            // } else {
            //     // 不是resolved那么就加入到作业队列里面
            //     this[thenables].push(thenable);
            // }

            // this.catch(catchable);
            // this[settleHandle](thenable, RESOLVED, this[thenables]);
            // this.catch(catchable);

            // 调用then要返回一个promise
            return this[linkPromise](thenable, catchable);
        }
        catch (catchable) {
            // this[settleHandle](catchable, REJECTED, this[catchables]);
            return this[linkPromise](undefined, catchable);
        }

        static resolve(data) {
            if (data instanceof MyPromise) {
                return data;
            }
            return new MyPromise((resolve, reject) => {
                resolve(data);
            })
        }

        static reject(data) {
            //reject 不返回对象
            return new MyPromise((resolve, reject) => {
                reject(data);
            })
        }

        static all(promises) {
            return new MyPromise((resolve, reject) => {
                const results = promises.map(p => {
                    const obj = {
                        result: false,
                        isResolved: false
                    };
                    p.then(data => {
                        obj.result = data;
                        obj.isResolved = true;
                        //判断是否全部完成
                        const isResolved = results.filters(r => !r.isResolved);
                        if (isResolved.length === 0) {
                            //全部完成
                            resolve(results.map(r => r.result));
                        }
                    }, err => {
                        // 只要有一个失败整体就失败
                        reject(err);
                    })
                    return obj;
                })
            })
        }

        static race(promises) {
            //只要有一个resolved或者rejected那么就结束
            return new MyPromise((resolve, reject) => {
                promises.forEach(p => {
                    p.then(data => {
                        resolve(data);
                    }, err => {
                        reject(err);
                    })
                })
            })

        }
    }
})();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值