chenyinkai / blog

学习笔记,技术心得,疑难困惑,生活总结。喜欢的请star。。
42 stars 1 forks source link

实现一个简单版本的Promise #23

Open chenyinkai opened 6 years ago

chenyinkai commented 6 years ago

简单版本的 Promise 实现,只有 then 方法

function MyPromise(executor){
    let self = this
    self.status = 'pending' // Promise当前的状态
    self.data = undefined // Promise的值
    self.onResolvedCallback = [] // Promise resolve时的回调函数集,因为在Promise结束之前有可能有多个回调添加到它上面
    self.onRejectedCallback = [] // Promise reject时的回调函数集,因为在Promise结束之前有可能有多个回调添加到它上面

    let resolve = (value) => {
        if (self.status === 'pending') {
            self.status = 'resolved'
            self.data = value
            for (let i = 0; i < self.onResolvedCallback.length; i++) {
                self.onResolvedCallback[i](value)
            }
        }
    }

    let reject = (reason) => {
        if (self.status === 'pending') {
            self.status = 'rejected'
            self.data = reason
            for (let i = 0; i < self.onRejectedCallback.length; i++) {
                self.onRejectedCallback[i](reason)
            }
        }
    }

    try { // 考虑到执行executor的过程中有可能出错,所以我们用try/catch块给包起来,并且在出错后以catch到的值reject掉这个Promise
        executor(resolve, reject) // 执行executor
    } catch (e) {
        reject(e)
    }
}
MyPromise.prototype.then = function (onResolved, onRejected) {
    let self = this
    let promise2

    // 根据标准,如果then的参数不是function,则我们需要忽略它,此处以如下方式处理
    onResolved = typeof onResolved === 'function' ? onResolved : function (value) {
        return value
    }
    onRejected = typeof onRejected === 'function' ? onRejected : function (reason) {
        throw reason
    }

    if (self.status === 'resolved') {
        // 如果promise1(此处即为this/self)的状态已经确定并且是resolved,我们调用onResolved
        // 因为考虑到有可能throw,所以我们将其包在try/catch块里
        return promise2 = new MyPromise(function (resolve, reject) {
            try {
                let result = onResolved(self.data)
                if (result instanceof Promise) { // 如果onResolved的返回值是一个Promise对象,直接取它的结果做为promise2的结果
                    result.then(resolve, reject)
                }
                resolve(result) // 否则,以它的返回值做为promise2的结果
            } catch (e) {
                reject(e) // 如果出错,以捕获到的错误做为promise2的结果
            }
        })
    }

    if (self.status === 'rejected') {
        return promise2 = new MyPromise(function (resolve, reject) {
            try {
                let result = onRejected(self.data)
                if (result instanceof Promise) {
                    result.then(resolve, reject)
                }
            } catch (e) {
                reject(e)
            }
        })
    }

    if (self.status === 'pending') {
        return promise2 = new MyPromise(function (resolve, reject) {
            self.onResolvedCallback.push(function (value) {
                try {
                    let result = onResolved(self.data)
                    if (result instanceof Promise) {
                        result.then(resolve, reject)
                    }
                } catch (e) {
                    reject(e)
                }
            })

            self.onRejectedCallback.push(function (reason) {
                try {
                    let result = onRejected(self.data)
                    if (result instanceof Promise) {
                        result.then(resolve, reject)
                    }
                } catch (e) {
                    reject(e)
                }
            })
        })
    }
}

测试

const MyPromiseTest = () => {
    return new MyPromise((resolve, reject) => {
        setTimeout(() => {
            let num = Math.random();
            resolve(num);
        }, 3000);
    })
}

MyPromiseTest().then((result) => {
    console.log(result);
})

3 秒后输出随机数