js 异步改成同步Promise

守护式等待 / 2023-08-23 / 原文

function Promise(executor) {
    let self = this;
    if (typeof executor !== 'function') throw new TypeError('Promise resolver ' + executor + ' is not a function');
    if (!(self instanceof Promise)) throw new TypeError('undefined is not a promise');

    self.state = 'pending';
    self.value = undefined;
    self.onfulfilledCallbacks = [];
    self.onRejectedCallbacks = [];

    const change = function change(state, value) {
        if (self.state !== 'pending') return;
        self.state = state;
        self.value = value;

        const callbacks = self.state === "fulfilled" ? self.onfulfilledCallbacks : self.onRejectedCallbacks;
        for (let i = 0; i < callbacks.length; i++) {
            let callback = callbacks[i];
            if (typeof callback === 'function') callback(self.value);
        }

    };

    try {
        executor(function resolve(value) {
            change('fulfilled', value);
        }, function reject(reason) {
            change('rejected', reason);
        });
    } catch (err) {
        change('rejected', err.message);
    }
}

const resolvePromise = function resolvePromise(promise, x, resolve, reject) {
    if (x === promise) throw new TypeError('Chaining cycle detected for promise #<Promise>');
    if (x !== null && /^(object|function)$/i.test(typeof x)) {
        let then;
        try {
            then = x.then;
        } catch (err) {
            reject(err);
        }
        if (typeof then === 'function') {
            let called = false;
            try {
                then.call(x, function onfulfilled(x) {
                    if (called) return;
                    called = true;
                    resolvePromise(promise, x, resolve, reject);
                }, function onRejected(r) {
                    if (called) return;
                    called = true;
                    reject(r);
                });
            } catch (err) {
                if (called) return;
                reject(err);
            }
            return;
        }
    }
    resolve(x);
};
const handle = function handle(callback, value, promise, resolve, reject) {
    try {
        let x = callback(value);
        resolvePromise(promise, x, resolve, reject);
    } catch (err) {
        reject(err);
    }
};
Promise.prototype = {
    constructor: Promise,
    then: function then(onfulfilled, onRejected) {
        const self = this;
        let promise = null;
        if (typeof onfulfilled !== 'function') {
            onfulfilled = function onfulfilled(value) {
                return value;
            };
        }
        if (typeof onRejected !== 'function') {
            onRejected = function onRejected(reason) {
                throw reason;
            };
        }
        promise = new Promise(function (resolve, reject) {
            switch (self.state) {
                case 'fulfilled':

                    handle(onfulfilled, self.value, promise, resolve, reject);

                    break;
                case 'rejected':

                    handle(onRejected, self.value, promise, resolve, reject);

                    break;
                default:
                    self.onfulfilledCallbacks.push(function (value) {
                        handle(onfulfilled, value, promise, resolve, reject);
                    });
                    self.onRejectedCallbacks.push(function (reason) {
                        handle(onRejected, reason, promise, resolve, reject);
                    });
            }
        });
        return promise;
    },
    catch: function my_catch(onRejected) {
        return this.then(null, onRejected);
    }
};
if (typeof Symbol !== "undefined") Promise.prototype[Symbol.toStringTag] = 'Promise';
Promise.resolve = function resolve(value) {
    return new Promise(function (resolve) {
        resolve(value);
    });
};
Promise.reject = function reject(reason) {
    return new Promise(function (_, reject) {
        reject(reason);
    });
};
const isPromise = function isPromise(x) {
    if (x !== null && /^(object|function)$/i.test(typeof x)) {
        if (typeof x.then === 'function') {
            return true;
        }
    }
    return false;
};
Promise.all = function all(promises) {
    if (!Array.isArray(promises)) throw new TypeError('promises must be an Array');
    let n = 0,
        results = [];
    return new Promise(function (resolve, reject) {
        for (let i = 0; i < promises.length; i++) {
            (function (i) {
                let promise = promises[i];
                if (!isPromise(promise)) promise = Promise.resolve(promise);
                promise.then(function onfulfilled(value) {
                    n++;
                    results[i] = value;
                    if (n >= promises.length) resolve(results);
                }).catch(function onRejected(reason) {
                    reject(reason);
                });
            })(i);
        }
    });
};
Promise.deferred = function deferred() {
    const result = {};
    result.promise = new Promise(function (resolve, reject) {
        result.resolve = resolve;
        result.reject = reject;
    });
    return result;
};

const _promise_ = new Promise((resolve, reject) => {
    console.log(`sync..`)
    resolve(101)
})

_promise_.then((data) => {
    console.log(`sync..`);
    console.log(data);
})

_promise_.then((data) => {
    console.log(888);
    console.log(data);
})

let p1 = new Promise(function (resolve, reject) {
    resolve(`宝哥说给你10000000`);
});
p1.then(e => console.log(e));

let p2 = new Promise(function (resolve, reject) {
    reject(`阿布反手拒绝你一个99999`);
});
p2.catch(err => console.log(`err`, err));

Promise.resolve("13122223333").then(v => console.log(v));