weekCodeing / interview-answe

🌍 前端程序员训练 求星星 ✨ 各位同学可以在issues中提问,无论是实际项目中遇到的问题,或者是技术问题都可以, 大家一起解决💯 👍 😄。
http://www.dadaqianduan.cn/
76 stars 9 forks source link

212.必须要会的手写Promise #212

Open webVueBlog opened 4 years ago

webVueBlog commented 4 years ago

[js]

webVueBlog commented 4 years ago

Promise是一个管理异步编程的方案,它是一个构造函数,每次使用可用new创建实例;它有三种状态:pending、fulfilled和rejected,这三种状态不会受外界影响,状态只能由pending变为fullfilled(成功),pending变为rejected(失败),且一旦改变就不会再改变,在状态改变后,它会返回成功的结果或者失败的原因,它对外抛出了resolve、reject、catch、finally、then、all、race、done,在最新的提案中,添加了allSettled方法,它不管成功、失败都会返回,接下来,我们自己实现整个Promise

webVueBlog commented 4 years ago
class MyPromise{
    constructor(executor) {
        this.status = "pending";     // 初始化状态为pending
        this.value = undefined;      // 初始化返回的成功的结果或者失败的原因

        // 这里是resolve方法,成功后执行,将状态改变为resolved,并且将结果返回
        let resolve = result => {
            if(this.status !== "pending") return;  // 状态一旦改变,就不会再变
            this.status = "resolved";
            this.value = result;
        }

        // 这里是reject方法,异常时执行,状态改为rejected,并且将失败的原因返回
        let reject = reason => {
            if(this.status !== "pending") return;
            this.status = "rejected";
            this.value = reason;
        }
        // try、catch捕获异常,如果错误,执行reject方法
        try {
            executor(resolve, reject)
        } catch(err) {
            reject(err)
        }
    }
}
webVueBlog commented 4 years ago
then(resolveFn, rejectFn) {
    // 如果传入的两个参数不是函数,则直接执行返回结果
    let resolveArr = [];
    let rejectArr = [];

    if(typeof resolveFn !== "function") {
        resolveFn = result => {
            return result;
        }
    }

    if(typeof rejectFn !== "function") {
        rejectFn = reason => {
            return MyPromise.reject(reason);
        }
    }

    return new Mypromise((resolve, reject) => {
        resolveArr.push(result => {
            try {
                let x = resolveFn(result);

                if(x instanceof MyPromise) {
                    x.then(resolve, reject)
                    return;
                }

                resolve(x);
            } catch(err) {
                reject(err)
            }
        })

        rejectArr.push(reason => {
            try {
                let x = rejectFn(reason);

                if(x instanceof MyPromise) {
                    x.then(resolve, reject)
                    return;
                }

                resolve(x);
            } catch(err) {
                reject(err)
            }
        })
    })
}