Javascript-手写Promise(超详细,适合小白~)

//实例化一个MyPromise对象
class MyPromise {
    //创建constructor函数(考点:new实例化后之后发生了什么?答:1.创建一个空对象,作为要返回的对象实例。2.将这个空对象的原型__proto__,指向构造函数的prototype属性。3.将空对象赋值给函数内部的this关键字,即把constructor函数内部的this指向空对象。4.执行constructor内部代码。5.如果constructor内部有return并且是一个对象,那么new实例化返回的就是return后面的对象;否则不管return语句返回this对象,即前面创建的空对象。~这是因为new总是返回一个对象,如果对于普通函数而言,即使有return,但如果不是对象,则忽略,创建空对象,由于没有this指定属性,返回空对象。)new代码参考‘手写new.js'。
    constructor(executor) {
        //传入的参数是executor函数,即promise时指定的执行器函数。

        //对于promise最重要的是状态(state)、成功的值(value)和失败的原因(reason)、执行器函数(executor)。
        this.state = 'pending';
        this.value = undefined;
        this.reason = undefined;
        //由于then是同步挂载,故对于异步的promise要把指定的回调挂载到自身,需要时候再触发。
        this.onFulfilledCallbacks = [];
        this.onRejectedCallbacks = [];

        //定义resolve和reject状态改变函数。
        const resolve = (value) => {
            //promise A+规定其状态初始化为pending,并且之后只能改变一次,要么为Fuifilled;要么为Rejected;不允许之后再变化状态。
            if (this.state === 'pending') {
                //一旦执行函数,改变状态并且把传入的值赋值给自身的value属性;依次执行挂载到身上的所有方法。
                this.state = 'Fulfilled';
                this.value = value;
                this.onFulfilledCallbacks.forEach(fn => fn());
            } else {
                return;
            }
        };
        const reject = (reason) => {
            if (this.state === 'pending') {
                this.state = 'Rejected';
                this.reason = reason;
                this.onRejectedCallbacks.forEach(fn => fn());
            } else {
                return;
            }
        };
        //调用传入的执行器executor函数,将把resolve和reject两种状态改变函数作为参数传入。并且包裹一个错误捕获try/catch,一旦发生错误,比如传入一个未定义的变量,可以在这里捕获。
        try {
            executor(resolve, reject);
        } catch (error) {
            reject(error);
        }
    }
    //定义then方法,并且把指定的成功和失败的回调作为参数传入。
    then(onFulfilled, onRejected) {
        //首先判断指定的回调类型,如果不是由一个函数,则把其包装成为一个函数。
        if (typeof onFulfilled !== 'function') {
            //对于指定的成功回调包装成普通箭头函数
            onFulfilled = (value) => value
        };
        if (typeof onRejected !== 'function') {
            //如果then指定的失败的回调不是一个函数,抛出错误;并且这个错误会在78或者101行捕获。
            onRejected = (error) => { throw error }
        }

        //promise规定,每一个then返回一个新的promise对象。
        const pp = new MyPromise((resolve, reject) => {
            //x代表上一次promise指定的回调执行结果。这里包装一个定时器是为了模拟异步获取x值。
            let x;
            //Promise A+规定.then返回的promise对象pp是不允许等于回调函数的返回结果x。

            //注意这里的this指向谁调用这个then方法,指向constructor中的this。
            if (this.state === 'Fulfilled') {
                //这里包装一个定时器是为了接收到.then返回的promise对象,必须要在初始化之后才能获得,因此利用定时器模拟异步,推向队列。
                setTimeout(() => {
                    try {
                        //先执行回调并且把返回值赋值给x。
                        x = onFulfilled(this.value);
                        //调用resolvePromise函数,根据x的情况判断调用.then返回的promise是否成功或者失败。
                        this.resolvePromise(pp, x, resolve, reject);
                    } catch (error) {
                        reject(error)
                    }
                }, 0)
            };
            if (this.state === 'Rejected') {
                //捕获失败后抛出的错误
                setTimeout(() => {
                    try {
                        x = onRejected(this.reason)
                        this.resolvePromise(pp, x, resolve, reject);
                    } catch (error) {
                        reject(error)
                    }
                }, 0)
            };
            if (this.state === 'pending') {
                //如果是异步的,先把指定的回调推向自身的回调数组保存。
                this.onFulfilledCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            x = onFulfilled(this.value);
                            this.resolvePromise(pp, x, resolve, reject);
                        } catch (error) {
                            reject(error)
                        }
                    }, 0)

                });
                this.onRejectedCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            x = onRejected(this.reason);
                            this.resolvePromise(pp, x, resolve, reject);
                        } catch (error) {
                            reject(error)
                        }
                    }, 0)
                });
            };

        });
        //返回一个promise实例。
        return pp;
    }
    //定义一个处理回调返回的promise是否成功/失败的函数;注意这里传入参数resolve和reject是.then返回promise的resolve和reject。
    resolvePromise(pp, x, resolve, reject) {
        //这里不符合A+规范,返回一个错误。
        if (pp === x) {
            reject('TypeError')
        }
        //如果.then中指定的回调函数执行后的返回值如果是object或者function,默认是promise实例对象,对其自动绑定一个then方法,如果成功,则其传入的resolve执行,.then返回promise成功,反之失败。
        if ((typeof x === 'object' && x !== null) || x === 'function') {
            //非普通值
            x.then(y => {
                resolve(y)
            }, r => {
                reject(r);
            });
        } else {
            //对于普通值,直接成功。
            resolve(x)
        }
    }
    //定义promise身上的静态成员~static(考点:静态成员与实例成员)
    static all(arg) {
        //同样规定返回的是一个promise对象。
        return new MyPromise((resolve, reject) => {
            //all执行的是并发操作
            let valueAll = [], count = 0;
            arg.forEach(item => {
                item.then((value) => {
                    valueAll.push(value);
                    count++;
                    //全部成功才会把返回的实例状态变为成功
                    if (count === arg.length) {
                        resolve(valueAll)
                    };
                }, (reason) => {
                    //只要失败,状态变为失败
                    reject(reason);
                })
            });
        })
    }
    static race(arg) {
        //类似all,这里是返回第一个promise对象返回的结果。
        return new MyPromise((resolve, reject) => {
            arg.forEach(item => {
                item.then((value) => {
                    resolve(value)
                }, (reason) => {
                    reject(reason);
                })
            });
        })
    }
    static resolve() {
        //返回一个成功的实例(undefined)
        return new MyPromise((resolve, reject) => {
            resolve();
        })
    }
    static reject() {
        //返回一个失败的实例(undefined)
        return new MyPromise((resolve, reject) => {
            reject();
        })
    }
};

部分代码片段和思路参考前端小夏老师https://b23.tv/3rmhkf3

仍有很多待优化的地方,欢迎各位大佬交流👏

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值