Promise 原理篇 => 从 0 到 1 构建一个 Promise

在不了解 Promise 的情况下,建议先阅读 Promise 的使用篇

注意点:

  • executor 函数立即执行
  • 状态不可逆 (pending -> fulfilled 或者 pending -> rejected)
  • resolve/reject 执行之后立即改变状态
  • .then 里面的内容异步执行并且返回一个新的 Promise
  • 在不出现错误的情况下 onFulfilled/onRejected 的返回值作为下一个 Promise 的成功回调的参数
// 状态常量
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

// Promise 类
function LPromise(executor) {
    this.status = PENDING   // 当前状态
    this.value = undefined  // 当前值
    this.onFulfilled = []    // 缓存成功回调
    this.onRejected = []     // 缓存失败回调
    this.resolveFn = body => {  // resolve 函数
        // 只有当当前状态为 pedding 才触发
        if (this.status !== PENDING) return

        this.status = FULFILLED
        this.value = body
        // 触发成功的回调
        // 主要用于 executor 里面含有异步逻辑的处理
        // 当 excutor 函数里面是同步逻辑的时候 this.onFulfilled 是一个空的数组
        this.onFulfilled.forEach(cb => cb())
    }
    this.rejectFn = error => {  // reject 函数
        if (this.status !== PENDING) return

        this.status = REJECTED
        this.value = error
        this.onRejected.forEach(cb => cb())
    }

    // 立即执行 executor 函数
    // try catch 是为了防止 executor 里面内容发生异常
    try {
        executor(this.resolveFn, this.rejectFn)
    } catch (e) {
        this.rejectFn(e)
    }
}

// then 方法
// 接收一个成功回调(onFulfilled) 一个失败回调(onRejected)
LPromise.prototype.then = function (onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => { }
    onRejected = typeof onRejected === 'function' ? onRejected : () => { }

    // 链式调用
    const _promise = new LPromise((resolve, reject) => {
        // 异步执行 then 函数里面的内容
        setTimeout(() => {
            // 当 excutor 函数里面是同步逻辑或者是执行在这之前的异步函数的时候 才会走到这里
            if (this.status === FULFILLED) {
                const result = onFulfilled(this.value)
                resolve(result)
            }

            // 当 excutor 函数里面是同步逻辑或者是执行在这之前的异步函数时候 才会走到这里
            if (this.status === REJECTED) {
                const result = onRejected(this.value)
                reject(result)
            }


            // 当 excutor 函数里面是异步逻辑并异步在这之后执行的时候 才会走到这里
            if (this.status === PENDING) {
                // 缓存用户传进来的 onFulfilled、onRejected 回调函数
                // 当用户主动触发 resolve/reject 的时候再调用

                this.onFulfilled.push(() => {
                    // 将当前回调返回的结果
                    // 返回到下一个 Promise 的成功回调中
                    try {
                        const result = onFulfilled(this.value)
                        resolve(result)
                    } catch (e) {
                        reject(e)
                    }

                })

                this.onRejected.push(() => {
                    // 将当前回调返回的结果
                    // 返回到下一个 Promise 的成功回调中
                    try {
                        const result = onRejected(this.value)
                        resolve(this.value)
                    } catch (e) {
                        reject(e)
                    }
                })
            }
        }, 0)
    })

    return _promise
}

// 捕获错误
// 接收一个失败回调(onRejected)
LPromise.prototype.catch = function (onRejected) {
    this.then(null, onRejected)
}

LPromise.resolve = function (value) {
    return new LPromise((resolve, reject) => {
        resolve(value)
    })
}

LPromise.reject = function (value) {
    return new LPromise((resolve, reject) => {
        reject(value)
    })
}

测试


console.log('script start')

const lp1 = new LPromise((resolve, reject) => {
    a
})

lp1.then(body => { }, error => {
    console.log(error)
})

const lp2 = new LPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('sleep 1000ms')
    }, 1000)
})

lp2.then(body => {
    console.log(body)
    return 1
}, null)

const lp3 = new LPromise((resolve, reject) => {
    setTimeout(() => {
        reject('失败了')
    }, 1000)
})

lp3.then()
lp3.catch(fail => console.log(fail))

const lp4 = new LPromise((resolve, reject) => {
    setTimeout(() => {
        resolve(1)
    }, 1)
})

lp4
    .then(body => {
        console.log(body)
        return '嘻哈'
    }, null)
    .then(body => {
        console.log(body)
        return 1
    }, null)

const lp5 = new LPromise((resolve, reject) => {
    setTimeout(() => {
        resolve('测试 then 里面抛出异常')
    }, 10)
})

lp5
    .then(body => {
        console.log(body)
        console.log(b)

        return '嘻哈'
    }, null)
    .then(null, error => {
        console.log('上一个 then 里面抛出了异常,被我接收到了哦!!')
        console.log(error)
    })

LPromise.resolve(setTimeout(() => console.log('setTimeout'), 1000))
    .then(body => console.log(body, 'Promise.resolve'))
LPromise.reject(setTimeout(() => console.log('setTimeout'), 1000))
    .then(null, body => console.log(body, 'Promise.reject'))

console.log('script end')

以上输出结果:
> script start
> script end
> ReferenceError: a is not defined
> 1
> 嘻哈
> 13, Promise.resolve
> 15, Promise.reject
> 测试 then 里面抛出异常
> 上一个 then 里面抛出了异常,被我接收到了哦!!
> ReferenceError: b is not defined
> sleep 1000ms
> 失败了
> setTimeout
> setTimeout

【笔记不易,如对您有帮助,请点赞,谢谢】

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容