es6手动实现promise 和效果和浏览器底层实现的效果一样

简介: es6手动实现promise 和效果和浏览器底层实现的效果一样
/**
 * 手动实现promise的功能, 只能保证功能相同。用于来更加深刻的理解promise
 * 为什么这里要用一个立即执行函数,因为这里没有用模块化,所以用立即执行函数,防止定义的名字相同,导致全局污染
 * @type {{new(): MyPromise, prototype: MyPromise}}
 */
const MyPromise = (() => {
    // 定义一些常量
    const PENDING = "pending", // 等待状态(未决状态)
        RESOLVE = "resolved", // 成功状态 (已决状态)
        REJECT = "rejected", // 失败状态 (已决状态)
        thenables = Symbol("用于保存成功状态的队列"), //
        catchables = Symbol("用来保存失败状态的队列"), //
        promiseStatus = Symbol("PromiseStatus"), // 用符号来保存promise的状态,防止外部访问
        promiseValue = Symbol("PromiseValue"),  // promise的值
        changeStatus = Symbol("改变状态的函数"),
        execSettledCommon = Symbol("执行已决状态的公共方法"),
        createPromise = Symbol("用于创建一个新的promise,用于then或者catch方法后的链式调用");
    return class MyPromise {
        /**
         * 一进来创建promise实例是传入两个方法,一个是resolve, 一个是reject
         * @param executor
         */
        constructor(executor) {
            // 创建promise实例后的状态是pending,值是undefined
            this[promiseStatus] = PENDING;
            this[promiseValue] = undefined;
            this[thenables] = []; //后续处理函数的数组 -> resolved
            this[catchables] = []; //后续处理函数的数组 -> rejected
            // 成功的状态 已决
            const resolve = (data) => {
                this[changeStatus](RESOLVE, data, this[thenables]);
            };
            // 失败的状态 已决
            const reject = (err) => {
                this[changeStatus](REJECT, err, this[catchables]);
            };
            // 这里的try catch 用于捕捉 promise里面抛出的错误,抛到上一层
            try {
                executor(resolve, reject)
            } catch (err) {
                reject(err);
            }
        }
        /**
         * 改变promise状态的方法
         * @param status 修改成对应的状态
         * @param value 修改的值
         * @param queue 修改状态的时候执行放入thenables 或者 catchables队列里面的函数
         */
        [changeStatus](status, value, queue) {
            // 因为promise的状态是单向传递的,不可逆转的,所以当只有状态为pending的时候才可以往往下走
            if (this[promiseStatus] === PENDING) {
                this[promiseStatus] = status;
                this[promiseValue] = value;
                // 当状态改变的时候,执行then/catch队列里面的对应函数
                queue.forEach(handler => handler(value));
            }
        }
        /**
         * 执行已决状态的后续函数的公共方法
         * @param handler 后续处理函数
         * @param status 当前状态
         * @param queue 如果当前状态是resolve或者reject, 放入对应的thenables 和 catchables的消息队列中
         */
        [execSettledCommon](handler, status, queue) {
            // 只有当传入的函数是一个函数的时候,才会去执行该函数
            if (typeof handler !== "function") {
                return;
            }
            if (this[promiseStatus] === status) {
                // 用于模拟promise 是异步的,promise会放到微队列中执行
                setTimeout(() => {
                    handler(this[promiseValue]);
                }, 0);
            } else {
                // 否则放入消息队列
                queue.push(handler);
            }
        }
        /**
         * 用于创建返回的promise的方法
         * @param thenHandler then 后续函数
         * @param catchHandler catch 后续函数
         * @returns {MyPromise}
         */
        [createPromise](thenHandler, catchHandler) {
            /**
             * 用于内部调用 执行then/catch 的后续函数的操作, 使得外部不能访问,只给内部使用
             * @param data 调用传入的数据
             * @param handler 传入的then 或者catch 函数
             * @param resolve 成功的毁掉
             * @param reject 失败的毁掉
             */
            function exec(data, handler, resolve, reject) {
                try {
                    // 执行通过then函数来改变状态
                    const result = handler(data);
                    // 这里需要判断result 返回的是不是一个promise对象,如果是promise对象,直接直接调用then(成功状态下),或者调用catch
                    if (result instanceof MyPromise) {
                        result.then(res => {
                            resolve(res);
                        }, err => {
                            reject(err);
                        })
                    } else {
                        resolve(result);
                    }
                } catch (e) {
                    reject(e)
                }
            }
            return new MyPromise((resolve, reject) => {
                // 使用then一直链式调用
                this[execSettledCommon](data => {
                    exec(data, thenHandler, resolve, reject);
                }, RESOLVE, this[thenables]);
                // 使用catch一直链式调用
                this[execSettledCommon](err => {
                    exec(err, catchHandler, resolve, reject);
                }, REJECT, this[catchables]);
            })
        }
        /**
         * 用于接收promise的状态, 也就是resolved状态,或者失败的rejected状态
         * @param thenHandler 成功的处理函数
         * @param catchHandler 失败的处理函数
         */
        then(thenHandler, catchHandler) {
            // 因为我们的then 函数或者catch函数放入createPromise 这里面处理了
            // this[execSettledCommon](thenHandler, RESOLVE, this[thenables]);
            // // 如果在then里面传了catchHandler的函数,执行下面这个代码
            // this.catch(catchHandler);
            return this[createPromise](thenHandler, catchHandler)
        };
        /**
         * 用于接收promise失败的状态
         * @param catchHandler 失败的处理函数
         */
        catch(catchHandler) {
            // this[execSettledCommon](catchHandler, REJECT, this[catchables]);
            return this[createPromise](undefined, catchHandler)
        };
        /**
         * 当所有的promise代码全部完成, 就返回成功的集合,失败一个着返回全部失败
         * @param proms promise 数组
         * @returns {MyPromise}
         */
        static all(proms) {
            return new MyPromise((resolve, reject) => {
                const promsArrs = proms.map(p => {
                    const obj = {
                        hasDone: false,
                        resultData: undefined,
                    };
                    p.then(res => {
                        obj.hasDone = true;
                        obj.resultData = res;
                        // 判断promise数组里面的promise对象是否全部完全
                        const hasFinishArr = promsArrs.filter(item => !item.hasDone);
                        if (hasFinishArr.length === 0) {
                            // 代表所有的promise都已经完成
                            resolve(promsArrs);
                        }
                    }, err => {
                        reject(err);
                    });
                    return obj;
                })
            })
        }
        /**
         * 当所有的promise数组只要有一个成功 就返回成功,失败就返回失败
         * @param proms promise 数组
         * @returns {MyPromise}
         */
        static race(proms) {
            return new MyPromise((resolve, reject) => {
                proms.forEach(p => {
                    p.then(res => {
                        resolve(res);
                    }, err => {
                        reject(err);
                    })
                })
            })
        }
        /**
         * promise成功的直接调用
         * @param data 结果
         * @returns {MyPromise}
         */
        static resolve(data) {
            // 判断结果是不是一个promise对象
            if (data instanceof MyPromise) { // 如果是promise对象,直接返回就好
                return data;
            } else { // 不是promise对象,直接返回一个promise对象
                return new MyPromise((resolve, reject) => {
                    resolve(data);
                })
            }
        }
        /**
         * promise的失败的直接调用
         * @param err 错误的原因 错误原因直接返回一个promise对象,不会阻塞代码的执行
         * @returns {MyPromise}
         */
        static reject(err) {
            return new MyPromise((resolve, reject) => {
                reject(err)
            })
        }
    }
})();


使用方法


<script src="Promise.js"></script>
<script>
    const pro = new MyPromise((resolve, reject) => {
        resolve(12323)
    });
    pro.then(res => {
        console.log("第一次成功:结果是", res);
        return "第一次成功返回";
    }, err => {
        console.log("第一次失败:结果是", err);
        throw "第一次失败返回"
    }).then(res => {
        console.log("第二次成功:结果是", res);
        return "第二次成功返回";
    }, err => {
        console.log("第二次失败:结果是", err);
        throw "第二次失败返回"
    }).then(res => {
        console.log("第三次成功:结果是", res);
        return "第三次成功返回";
    }, err => {
        console.log("第三次失败:结果是", err);
        throw "第三次失败返回"
    }).then(res => {
        console.log("第四次成功:结果是", res);
        return "第四次成功返回";
    }, err => {
        console.log("第四次失败:结果是", err);
        throw "第四次失败返回"
    }).catch(err => {
        console.log("最后的失败结果:", err);
    })
    // const pro1 = new Promise((resolve, reject) => {
    //     resolve(1)
    // });
    // pro1.then(res => {
    //     console.log(res);
    // })
    // console.log(2343244)
</script>


结果:


20200619151333245.png

相关文章
|
4月前
|
前端开发
理解 ES6 中的 Promise
【10月更文挑战第24天】ES6 中的 Promise 是一种用于处理异步操作的机制,它提供了一种更优雅、更可控的方式来处理异步任务的结果。Promise 可以看作是对异步操作结果的一种承诺,它可以处于三种不同的状态:Pending(等待中)、Fulfilled(已完成,即成功)和 Rejected(已拒绝,即失败)。
|
5月前
|
前端开发 JavaScript 小程序
JavaScript的ES6中Promise的使用以及个人理解
JavaScript的ES6中Promise的使用以及个人理解
55 1
|
5月前
|
前端开发 Java
说说你对es6中promise的理解?
说说你对es6中promise的理解?
23 1
|
5月前
|
前端开发 Java
说说你对es6中promise的理解?
说说你对es6中promise的理解?
|
7月前
|
前端开发
手写实现ES6的Promise.all()和Promise.race()函数
这篇文章介绍了如何手写实现ES6的`Promise.all()`和`Promise.race()`函数,提供了实现这两个Promise聚合函数的详细代码示例,并展示了如何使用它们。
手写实现ES6的Promise.all()和Promise.race()函数
|
6月前
|
前端开发 JavaScript
ES6新标准下JS异步编程Promise解读
ES6新标准下JS异步编程Promise解读
56 3
|
5月前
|
存储 前端开发 JavaScript
关于 ES6 中 Promise 的面试题
关于 ES6 中 Promise 的面试题
36 0
|
8月前
|
前端开发 JavaScript
ES6 中 Promise对象使用学习
ES6 中 Promise对象使用学习
62 1
|
7月前
|
前端开发 JavaScript
ES6新特性(五):Promise优雅地处理异步
ES6新特性(五):Promise优雅地处理异步
|
9月前
|
JSON 前端开发 JavaScript
ES6引入Promise和async/await解决异步问题
【6月更文挑战第12天】ES6引入Promise和async/await解决异步问题。Promise处理异步操作,有pending、fulfilled、rejected三种状态,支持链式调用和并行处理。async/await是基于Promise的语法糖,使异步代码更同步化,提高可读性。两者都是处理回调地狱的有效工具,开发者应根据需求选择合适的方式。
68 3

热门文章

最新文章