闲来无事温习 Promise

什么是 Promise

将异步回调嵌套的代码变成链式调用的一种方法。

原理上分析:

一个 Promise 必处于以下状态之一:

  • pending: 未决议 // 初始值
  • resolved: 已解决
  • rejected: 已失败

pending 状态下可以敲定为 resolved / rejected,只能敲定一次,之后不再改变。

Promise 接受一个执行者函数,会同步调用它,并交给个他两个决议的方法(resolved、rejected)执行者函数内部必须明确的调用其中一个。决议之后,就清空 then 添加的对应状态的任务列表(对应 resolved, rejected 状态),这是 Promise 做到异步回调 ”承上启下” 的重要一步。

每一个 then 在调用时就会返回一个默认的 Promise 实例(这支持了链式调用 then().then()),该 Promise 的决议值是在 then 接受的 onResolved / onRejected 中选择一个调用并求值,选择哪个就由上层的 Promise 的决议状态决定,上层为 fulfilled 则调用 onResolved,为 rejected 则调用 onRejected;到此为止,还不能直接 resolve 回调的返回值,如果这个返回值还是 Promise 的话,就需要递归继续求值,直到值为非 Promise。

自实现Promise

建议仔细阅读这篇文章:史上最最最详细的手写Promise教程

以下是我的实现:没有满足 PromiseA+规范 中的所有细节,但用来理解原理足够了。

/**
 * Promise State: pending, resolved, rejected
 * 
 * 使用方法:
 * new Promise((resolve, reject) => { // resolve/reject })
 * .then(() => {}, () => {})
 * .catch(e => { ... })
 * 
 */

class MyPromise {
    constructor(excuter) {
        this.state = "pending";
        this.value = undefined;
        this.reason = undefined;
        this.onResolvedList = [];
        this.onRejectedList = [];

        const resolve = (value) => {
            if (this.state === "pending") {
                this.state = "resolved";
                this.value = value;
                this.onResolvedList.forEach(cb => {
                    cb(this.value);
                });
            }
        };

        const reject = (reason) => {
            if (this.state === "pending") {
                this.state = "rejected";
                this.reason = reason;
                this.onRejectedList.forEach(cb => {
                    cb(this.reason);
                });
            }
        };

        try {
            excuter(resolve, reject);
        } catch (error) {
            reject(error);
        }
    }

    then(onResolved, onRejected) {
        return new MyPromise((resolve, reject) => {
            onResolved = typeof onResolved ===  "function" ? onResolved : value => value;
            onRejected = typeof onRejected === "function" ? onRejected : (reason) => {
                throw reason;
            };
            const _onResolved = () => {
                setTimeout(() => {
                    try {
                        let x = onResolved(this.value);
                        this.handlePromise(x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                });
            };
            const _onRejected = () => {
                setTimeout(() => {
                    try {
                        let x = onRejected(this.reason);
                        this.handlePromise(x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                });
            };
            if (this.state === "pending") {
                this.onResolvedList.push(() => _onResolved());
                this.onRejectedList.push(() => _onRejected());
            }
            if (this.state === "resolved") _onResolved();
            if (this.state === "rejected") _onRejected();
        });
    }

    catch(onRejected) {
        return this.then(null, onRejected);
    }

    /**
     * if x is Promise
     * x.then getValue
     * 
     * if x not Proimse
     * return x
     */
    handlePromise(x, resolve, reject) {
        let called = false;
        try {
            if (x !== undefined && x !== null && typeof x.then === "function") {
                if (called) return;
                called = true;
                x.then(v => {
                    // maybe v also promise
                    setTimeout(() => {
                        this.handlePromise(v, resolve, reject);
                    });
                }, (e) => {
                    if (called) return;
                    called = true;
                    reject(e);
                });
            } else {
                if (called) return;
                called = true;
                resolve(x);
            }
        } catch (error) {
            if (called) return;
            called = true;
            reject(error);
        }
    }
}

// test
let p1 = new MyPromise((resolve, reject) => {
    setTimeout(() => {
        resolve("delay 100ms p1");
    }, 100);
}).then(v => {
    console.log("then recvie value: ", v);
    return new MyPromise((resolve, reject) => {
        setTimeout(() => {
            resolve("delay 1000ms p1.then");
        }, 1000);
    });
}).then((v) => {
    console.log("then recvie value: ", v);
    throw new Error("custom error");
}).catch(e => {
    console.log("cactch error: ", e);
});
复制代码

其他实现

Promise.reject 实现

class MyPromise {
    // 省略...
    reject(reason) {
        return new MyPromise((resolve, reject) => {
            rejected(reason);
        });
    }
}
复制代码

Promise.resolve 实现

class MyPromise {
    // 省略...
    resolve(value) {
        return new MyPromise((resolve, reject) => {
            resolve(value);
        });
    }
}
复制代码

Promise.catch 实现

class MyPromise {
    // 省略...
    catch(onRejected) {
        this.then(null, onRejected);
    }

}
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享