一步步实现 Promise

  1. 实现构造器
  2. 实现 resolve 和 reject
  3. 实现同步的 then
  4. 实现异步的 then
  5. 实现可链式调用的 then
  6. 参考链接

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

使用的 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


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论。
我的空间