一步步实现Promise

实现了但没完全实现。。。

使用的ES6的class方式实现的。
参考掘金作者Sunshine_Lin的实现,链接在本文末尾。

实现构造器

要点:

  1. promise有三个状态,分别是pending fulfilled rejected,所以实例需要一个保存这个状态的变量。
  2. promise需要保存执行后的结果,又需要一个变量保存。
  3. 执行器exec里报错时,抛出异常,promise需要变为rejected状态

实现:

class MyPromise {
    constructor(exec) {
        this.promiseResult = undefined;
        this.promiseState = 'pending';
        try {
            exec(this.resolve, this.reject);
        } catch (e) {
            this.reject(e)
        }
    }
}

实现resolve和reject

要点:

  1. promise由pending变为fulfilled或者rejected后,就settle了不会再变了
  2. 要将resolve和reject的this绑定,防止跟随执行环境发生变化

实现:

class MyPromise {
    constructor(exec) {
       // ...
    }

    resolve = (value) => {
        if (this.promiseState === 'pending') {
            this.promiseResult = 'fulfilled'
            this.promiseState = value;
        }
    }

    reject = (reason) => {
        if (this.promiseState === 'pending') {
            this.promiseResult = 'rejected';
            this.promiseState = reason;
        }
    }
}

实现同步的then

要点:

  1. 因为then的两个参数可以省略,所以需要判断并设置默认值
  2. 根据promise的状态执行then的不同的函数

实现:

class MyPromise {
    // ...
    then = (onFulfilled, onRejected) => {
        // 因为then的两个参数可以省略,所以需要判断
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };

        if (this.promiseState === 'fulfilled') {
            onFulfilled(this.promiseResult)
        }
        if (this.promiseState === 'rejected') {
            onRejected(this.promiseResult)
        }
    }
}

同步的then,无法处理异步任务中的resolve和reject,因为同步执行时promiseState还在pending状态。不会执行onFulfilled或者onRejected函数。

实现异步的then

如何保证then方法是在resolve或这reject后才执行?
还需要在then做功夫,既然同步执行时promiseState还在pending状态,就再加一个if判断,当promise状态为pending时执行then,则将当前then方法传入的的onFulfilled函数和onRejected函数放入promise实例的所维护的数组中(我发现使用一个变量保存一个函数就可以,想不到为啥用数组,难道有多次then,而且第二次then时,promise还是pending状态?有这种场景???)。
放入数组的函数,在resolve或者reject真正执行的时候,才会被执行,此时就拿出数组的onFulfilled函数和onRejected函数,依次执行。
要点:

  1. 添加实例变量,保存在promise为pending状态时,then被调用时传入的函数参数
  2. 在resolve和reject内调用这些方法。

实现:

class MyPromise {
    constructor(exec) {
        this.promiseResult = undefined;
        this.promiseState = 'pending';
        // this.onFulFilledCallback = [];
        // this.onRejectedCallback = [];
        // 好像不用数组也行...
        this.onFulFilledCallback = null;
        this.onRejectedCallback = null;
        try {
            exec(this.resolve, this.reject);
        } catch (e) {
            this.reject(e)
        }
    }

    resolve = (value) => {
        if (this.promiseState === 'pending') {
            this.promiseState = 'fulfilled'
            this.promiseResult = value;
            // console.log(this.onFulFilledCallback.length);
            // this.onFulFilledCallback.shift()(value)
            if (this.onFulFilledCallback) {
                this.onFulFilledCallback(value)
            }
        }
    }

    reject = (reason) => {
        if (this.promiseState === 'pending') {
            this.promiseState = 'rejected';
            this.promiseResult = reason;
            if (this.onRejectedCallback) {
                this.onRejectedCallback(reason)
            }
        }
    }

    then = (onFulfilled, onRejected) => {
        // 因为then的两个参数可以省略,所以需要判断
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };


        if (this.promiseState === 'fulfilled') {
            onFulfilled(this.promiseResult);
        }
        if (this.promiseState === 'rejected') {
            onRejected(this.promiseResult);
        }
        if (this.promiseState === 'pending') {
            // this.onFulFilledCallback.push(onFulfilled);
            // this.onRejectedCallback.push(onRejected);
            this.onFulFilledCallback = onFulfilled;
            this.onRejectedCallback = onRejected;
        }
    }
}

实现可链式调用的then

要点:

  1. then会返回一个新的promise实例
  2. 原来的then的处理需要“通知”到新的promise实例
  3. 如果then的函数参数的返回值是promise,那么新的promise实例返回的状态取决于这个promise
  4. 如果返回值非promise,新promise对象就是fulfilled,且值为此返回值

实现:

class MyPromise {
    constructor(exec) {
        this.promiseResult = undefined;
        this.promiseState = 'pending';
        this.onFulFilledCallback = [];
        this.onRejectedCallback = [];
        try {
            exec(this.resolve, this.reject);
        } catch (e) {
            this.reject(e)
        }
    }


    resolve = (value) => {
        console.log('resolve: ', value, ' | ', this.onFulFilledCallback);
        if (this.promiseState === 'pending') {
            this.promiseState = 'fulfilled'
            this.promiseResult = value;
            while (this.onFulFilledCallback.length) {
                console.log('this.onFulFilledCallback.length: ', this.onFulFilledCallback.length);
                this.onFulFilledCallback.shift()(this.promiseResult)
            }
        }
    }

    reject = (reason) => {
        if (this.promiseState === 'pending') {
            this.promiseState = 'rejected';
            this.promiseResult = reason;
            while (this.onRejectedCallback.length) {
                this.onRejectedCallback.shift()(this.promiseResult)
            }
        }
    }
    then = (onFulfilled, onRejected) => {
        // 因为then的两个参数可以省略,所以需要判断并设置默认值
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val;
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };

        // 放到thenPromise里了
        // if (this.promiseState === 'fulfilled') {
        //     onFulfilled(this.promiseResult);
        // }
        // if (this.promiseState === 'rejected') {
        //     onRejected(this.promiseResult);
        // }
        // if (this.promiseState === 'pending') {
        //     this.onFulFilledCallback.push(onFulfilled);
        //     this.onRejectedCallback.push(onRejected);
        // }

        let thenPromise = new MyPromise((res, rej) => {
            // console.log(this.promiseState);
            // 此函数是一个箭头函数,exec也是箭头函数,所以resolvePromise声明时就会绑定到外面的promise,而不是这个promise
            const resolvePromise = tt => {
                try {
                    // 这个this是外面的,而不是这个新建的MyPromise的
                    const x = tt(this.promiseResult);  // 执行tt函数,拿到函数执行的结果,根据此结果进行判断。
                    if (x === this.thenPromise) {  // 这个判断不懂。。。
                        throw new Error("then返回一个新的promise而不是自身")
                    }
                    if (x instanceof MyPromise) {
                        // console.log('here');
                        x.then(res, rej);
                    } else {
                        // 非promise时primise实例就是调用resolve的fulfilled的
                        res(x);
                    }
                } catch (err) {
                    rej(err)
                }
            }

            if (this.promiseState === 'fulfilled') {
                // onFulfilled(this.promiseResult);
                resolvePromise(onFulfilled);
            }
            if (this.promiseState === 'rejected') {
                // onRejected(this.promiseResult);
                resolvePromise(onRejected);
            }
            // resolve或者reject是被异步调用的
            if (this.promiseState === 'pending') {
                this.onFulFilledCallback.push(() => {
                    resolvePromise(onFulfilled)
                });
                this.onRejectedCallback.push(() => {
                    resolvePromise(onRejected)
                });
            }
        })
        return thenPromise;
    }
}

参考链接

https://juejin.cn/post/6994594642280857630