编辑代码


function callAsync(fn, arg, callback, onError) {
    process.nextTick(function () {
        try {
            callback ? callback(fn(arg)) : fn(arg);
        } catch (e) {
            onError(e);
        }
    });
}

function CustomPromise(handle) {

    this.status = 'pending';
    this.value = undefined;
    this.reason = undefined;
    this.onFulfilledFunc = [];
    this.onRejectedFunc = [];

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

    function resolve(value) {
        if (this.status == "pending") {
            this.status = "resolved";
            this.value = value;
            this.onFulfilledFunc.forEach(fn => fn(value));
        }
    }

    function reject(reason) {
        if (this.status == "pending") {
            this.status = "rejected";
            this.reason = reason;
            this.onFulfilledFunc.forEach(fn => fn(reason));
        }
    }
}

CustomPromise.prototype.then = function (onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
    var self = this;
    var res = null;
    var returnPromise = new Promise(function (resolve, reject) {
        if (this.status == "resolved") {
            setTimeout(() => {
                try {
                    res = onFulfilled(self.value);
                    resolvePromise(returnPromise, res, resolve, reject);
                } catch (err) {
                    reject(err);
                }
            }, 0)


        }
        if (this.status == "rejected") {
            setTimeout(() => {
                try {
                    res = onrejected(self.value);
                    resolvePromise(returnPromise, res, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            }, 0)
        }

        if (this.status == "pedding") {
            self.onFulfilledFunc.push(function () {
                setTimeout(() => {
                    try {
                        res = onFulfilled(self.value);
                        resolvePromise(returnPromise, res, resolve, reject);
                    } catch (err) {
                        reject(err);
                    }
                }, 0)
            });

            self.onRejectedFunc.push(function () {
                setTimeout(() => {
                    try {
                        res = onrejected(self.value);
                        resolvePromise(returnPromise, res, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                }, 0)
            })
        }
    });
    return returnPromise;
}

CustomPromise.prototype.resolvePromise = function (promise, res, resolve, reject) {
    if (promise === res) {//防止循环引用
        return reject(new TypeError('循环引用'))
    }

    let called;//防止重复执行

    if (res !== null && (typeof res === 'function' || typeof res === 'object')) {
        try {//防止promise执行报错
            let then = res.then;//判断是否promise就判断是否存在then方法
            if (typeof then === 'function') {//如果返回的是promise,只需要在返回的promise的then方法中下一步需要执行的函数
                then.call(res, (res2) => {
                    if (called) return;
                    called = true;
                    resolvePromise(promise, res2, resolve, reject);//如果是promise继续递归执行,直到不是promise,依次执行外层的resolve,让promise状态改变
                })
            } else {//如果不是promise,有可能是undefine、onfulfilled或onrejected的返回的普通值,就直接将这个值返回,将外层的promise状态改变
                if (called) return;
                called = true;
                resolve(then)
            }
        } catch (e) {
            if (called) return;
            called = true;
            reject(e)
        }
    } else {
        resolve(res)
    }
}

CustomPromise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected);
}

CustomPromise.prototype.race = function (promises) {
    return new Promise((resolve, reject) => {
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(resolve, reject);
        }
    })
}

CustomPromise.prototype.all = function (promises) {
    let arr = [];
    let i = 0;
    function processData(index, data) {
        arr[index] = data;
        i++;
        if (i == promises.length) {
            resolve(arr);
        }
    };

    return new Promise((resolve, reject) => {
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(data => {
                processData[i, data];
            }, reject);
        };
    });
}