深入浅出现代 JavaScript—手写 Promise(1)

247 阅读2分钟

「这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战

JavaScript 核心就是异步编程,从回调函数、到 Promise 然后到今天 async/await 是 JavaScript 对于异步编程一步一步更新过来。所以面试应该不出意料都会或多或少问到这部分内容。

今天要去实现一个 Promise ,感觉只有自己实现一遍,才能印象深刻。我们就先尝试用一下 JavaScript 给我们封装好的 Promise。接下来今天工作就是简单自己去实现一下这个功能。

new Promise((resolve, reject) => {
    console.log("hello promise...")
})

Promise 接收一个函数作为参数,这个函数是一个 executor,在 Promise 构造函数内部会立即执行这个函数。

new Promise((resolve, reject) => {
    console.log("hello promise...");
    resolve("resolve")
}).then((value) => console.log(value));

resolve 用于将值返回给用户,用户可以会 then 注册一个回调函数来接收到这个值,reject 可以 then 注册第二个函数接受到个 Promise 没有被履行的原因和理由。

    class MyPromise {
        constructor(executor) {
            this.state = "pending";
            this.value = undefined;
            this.reason = undefined;
        }
    }

定义类 MyPromise 然后在构造函数内定义属性,state 表示 Promise 状态,value 是在履行 Promise 情况下,通过回调返回的值,reason 当没有履行 Promise 情况下,给出的理由。

class MyPromise {
    constructor(executor) {
        this.state = "pending";
        this.value = undefined;
        this.reason = undefined;

        let resolve = value => {
            if(this.state === 'pending'){
                this.state = 'fullFilled';
                this.value = value;
            }
        }

        let reject = reason => {
            if(this.state === 'pending'){
                this.state = 'rejected';
                this.reason = reason;
            }
        }

        

        executor(resolve,reject);
    }
}

每一个 Promise 都会有三个状态,而且状态从 pendding

  • pending
  • fullfilled
  • rejected

在 Promise 中构造器中,定义两个函数 resolvereject 在这 2 个函数更改 state 并且如 resolve 函数内部将 value 赋值给 this.value,而在 reject 中将 reason 赋值给 this.reason

接下来就是定义 then 函数,在 then 函数中根据 state 来执行传入不同的回调函数。

        class MyPromise {
            constructor(executor) {
                this.state = "pending";
                this.value = undefined;
                this.reason = undefined;

                let resolve = value => {
                    if(this.state === 'pending'){
                        this.state = 'fullFilled';
                        this.value = value;
                    }
                }

                let reject = reason => {
                    if(this.state === 'pending'){
                        this.state = 'rejected';
                        this.reason = reason;
                    }
                }

                executor(resolve,reject);
            }

            then(onFullFilled,onRejected){
                if(this.state === 'fullFilled'){
                    onFullFilled(this.value)
                }
                if(this.state === 'rejected'){
                    onRejected(this.reason);
                }
            }

            
        }