Rain120 / Web-Study

日常学习,工作写的笔记
66 stars 109 forks source link

如何实现Promise? #11

Open Rain120 opened 5 years ago

Rain120 commented 5 years ago

News

手写 Promise


const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

function Promise(executor) {
    let that = this;
    that.status = PENDING;
    that.value = undefined;
    that.reason = undefined;
    that.onFulfilledCallbacks = [];
    that.onRejectedCallbacks = [];

    function resolve(value) {
        if (value instanceof Promise) {
            return value.then(resolve, reject);
        }
        setTimeout(() => {
            if (that.status === PENDING) {
                that.status = FULFILLED;
                that.value = value;
                that.onFulfilledCallbacks.forEach(cb => cb(that.value));
            }
        });
    }

    function reject(reason) {
        setTimeout(() => {
            if (that.status === PENDING) {
                that.status = REJECTED;
                that.reason = reason;
                that.onRejectedCallbacks.forEach(cb => cb(that.reason));
            }
        });
    }
    try {
        executor(resolve, reject);
    } catch (e) {
        reject(e);
    }
}
// then, 如果状态是pending,那就加入不同状态的执行函数列表中
Promise.prototype.then = function (onFulfilled, onRejected) {
    const that = this;
    var newPromise;
    onFulfilled =
        typeof onFulfilled === "function" ? onFulfilled : value => value;
    onRejected =
        typeof onRejected === "function" ? onRejected : reason => reason;
    if (that.status === FULFILLED) {
        return newPromise = new Promise((resolve, reject) => {
            setTimeout(() => {
                try {
                    let x = onFulfilled(that.value);
                    resolvePromise(newPromise, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            });
        })
    }

    if (that.status === REJECTED) {
        return newPromise = new Promise((resolve, reject) => {
            setTimeout(() => {
                try {
                    let x = onRejected(that.reason);
                    resolvePromise(newPromise, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            });
        });
    }

    if (that.status === PENDING) {
        return newPromise = new Promise((resolve, reject) => {
            that.onFulfilledCallbacks.push((value) => {
                try {
                    let x = onFulfilled(value);
                    resolvePromise(newPromise, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            });
            that.onRejectedCallbacks.push((reason) => {
                try {
                    let x = onRejected(reason);
                    resolvePromise(newPromise, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            });
        });
    }
};
// 解析resolve是否是promise
function resolvePromise(newPromise, x, resolve, reject) {
    if (newPromise == x) {
        return reject(new TypeError('Chaining cycle'));
    }
    var called;
    if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
        try {
            var then = x.then;
            if (typeof then === 'funcition') {
                then.call(x, next => {
                    if (called) {
                        return;
                    }
                    called = true;
                    resolvePromise(newPromise, next, resolve, reject);
                }, err => {
                    if (called) {
                        return;
                    }
                    called = true;
                    reject(err);
                });
            } else {
                resolve(x);
            }
        } catch (err) {
            if (called) {
                return;
            }
            called = true;
            reject(err);
        }
    }
};