手写promise

/* 
宏队列和微队列: 
在js中执行栈在执行完同步任务后,查看执行栈是否为空,若为空去检查微任务队列是否为空,如果为空,就去执行宏任务,否则就一次性执行完所有宏任务。
执行顺序:同步任务 => 同步任务中的所有微任务 => 宏任务 => 宏任务中的所有微任务 => 下一个宏任务 => 宏任务中的所有微任务  这样形成事件循环机制。
        
宏任务: 定时器动画这些,例如 setTimeout,setInterval,requestAnimationFrame
微任务: js中的异步任务,例如 Promise,Object.observe,async/await
*/
(function () {
    /* 
        Promise有三种状态:
            初始态pending:创建Promise对象时,且没有调用resolve或者是reject方法,相当于是初始状态。
            成功态resolved(fulfilled):创建Promise对象时,在函数体中调用了resolve方法(即第一个参数)。
            失败态rejected:创建Promise对象时,调用reject函数(即第二个参数)。
        注意: 状态转换是不可逆的,不能从成功态/失败态 回到 初始态
    */
    const PENDING = 'pending';
    const RESOLVED = 'resolved';
    const REJECTED = 'rejected';
    //Promise构造函数
    //executor执行器函数
    /*
        Promise构造函数实现逻辑: 
            1. 数据需要一个初始状态,保存外部传递过来的数据,以及执行的回调函数(这个回调函数数据结构比较特殊:[{onResolved(){},onRejected(){}},{onResolved(){},onRejected(){}},.....])
            2. 两个实现函数:
                1)判断当前状态
                2)改变初始态,转变为成功态或者失败态
                3)保存外部传递的数据
                4)判断是否有未执行的回调函数,成功执行onResovled,失败执行onRejected
        已进入Promise函数中,使用执行器函数执行 executor(resolve, reject); 
    */

    /* 
        直接传入失败获成功的写法:
            new Promise(
                // 这里先会执行一段代码,再去改变状态
                () => {
                    console.log(resolve);
                },
                () => {
                    console.log(reject);
                }
            );
    */
    function Promise(executor) {
        const _this = this;
        this.status = PENDING; // 设置初始态
        this.data = undefined; // 用于接收外部传来的参数
        this.callbacks = []; // 每个元素的结构:onResolved(){},onRejected(){}
        // 改变promise状态,成功态
        function resolve(value) {
            // 判断当前状态是否为初始态,如果不是初始态的话直接return,因为不能从成功态/失败态 回到 初始态
            if (this.status !== PENDING) return;
            _this.status = RESOLVED;
            // 保存数据
            _this.data = value;
            // 存在未执行的回调,立即执行onResolved
            if (_this.callbacks.length > 0) {
                setTimeout(() => {
                    _this.callbacks.forEach(element => {
                        element.onResolved(value);
                    });
                });
            }
        }
        // 改变promise状态,失败态
        function reject(reason) {
            if (this.status !== PENDING) return;
            _this.status = REJECTED;
            // 保存数据
            _this.data = reason;
            // 存在未执行的回调,立即执行onResolved
            if (_this.callbacks.length > 0) {
                setTimeout(() => {
                    _this.callbacks.forEach(element => {
                        element.onRejected(reason);
                    });
                });
            }
        }
        // 实例一个promise是会有两个参数(resolve回调函数, reject回调函数)
        // 除了resolve和reject,还有可能自己抛出异常,会失败,此时需要一个try catch
        try {
            // 执行器函数,会立即执行
            // executor 是Promise类的一个回调函数
            // executor 执行resolve还是reject取决于外部
            executor(resolve, reject);
        } catch (error) {
            reject(error);
        }
    }
    /* 
        用到then或catch的话,Promise的写法是这样的:
            const p = new Promise();
            // p会执行一些事情来得到最后的状态,再根据状态执行then或者catch
            p.then(() => {
                console.log(resolve);
            }).catch(() => {
                console.log(reject);
            });
    */
    // then执行回调,接收成功的回调,返回一个新的promise
    Promise.prototype.then = function (onResolved, onRejected) {
        const _this = this;
        // 判断传递过来的参数是不是函数
        onResolved = typeof onResolved === 'function' ? onResolve : value => value; // 继续向下传递
        onRejected =
            typeof onRejected === 'function'
                ? onRejected
                : reason => {
                      throw reason;
                  }; // 抛出异常
        // 返回一个新的Promise对象
        return new Promise((resolve, reject) => {
            const handle = callback => {
                try {
                    // 执行then方法传递过来的函数,并将数据带过去
                    const result = onResolved(_this.data);
                    // 这个地方应该是个递归思想,看是不是里面还有一层promise
                    if (result instanceof Promise) {
                        result.then(resolve, reject);
                    }
                } catch (error) {
                    reject(error);
                }
            };
            if (this.status === PENDING) {
                // 状态为初始状态保存下来
                this.callbacks.push({
                    onResolved(value) {
                        handle(value);
                    },
                    onRejected(reason) {
                        handle(onRejected);
                    },
                });
            } else if (this.status === REJECTED) {
                //  如果回调是promise,return的promise结果就是这个promise结果
                setTimeout(() => {
                    handle(onResolved);
                });
            } else {
                //如果前面的promise返回的是失败的回调
                setTimeout(() => {
                    handle(onRejected);
                });
            }
        });
    };
    // catch执行回调,失败的回调
    Promise.prototype.catch = function (onRejected) {
        return this.then(undefined, onRejected);
    };
    // 以下四个是静态方法
    Promise.resolve = function (value) {
        return new Promise((resolve, reject) => {
            // instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
            if (value instanceof Promise) {
                value.then(resolve, reject);
            } else {
                resolve(value);
            }
        });
    };
    Promise.reject = function (reason) {
        return new Promise((resolve, reject) => {
            reject(reason);
        });
    };
    // 多个promise执行时
    Promise.all = function (promises) {
        let values = [];
        let resolvedCount = 0;
        return new Promise((resolve, reject) => {
            promises.forEach((p, index) => {
                Promise.resolve(p).then(
                    value => {
                        resolvedCount++;
                        values[index] = value;
                        if (resolvedCount == promises.length) {
                            resolve(values);
                        }
                    },
                    reason => {
                        // 只要有一个失败就失败
                        reject(reason);
                    }
                );
            });
        });
    };
    // 多个promise执行时
    Promise.race = function (promises) {
        return new Promise((resolve, reject) => {
            promises.forEach((p, index) => {
                Promise.resolve(p).then(
                    value => {
                        resolve(value);
                    },
                    reason => {
                        reject(reason);
                    }
                );
            });
        });
    };
})(window);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hoki802

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值