js原生方法promise的实现

一会儿就要回家过年了,再来手写一个promise吧,要不等着下班真的煎熬。。。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="author" content="杨欣">
    <title>手写promise</title>
</head>

<body>

    <script>
        // 第一版
        // class _Promise {
        //     constructor(handler) {
        //         // 判断参数是否不为函数
        //         if (typeof handler !== 'function') {
        //             throw new TypeError(`${handler} is not a function`)
        //         }
        //         this.state = 'pending'//初始状态
        //         this.value = null//最终返回值
        //         this.reason = null //失败原因
        //         let _this = this;
        //         const resolve = function (value) {
        //             if (_this.state === 'pending') {
        //                 _this.state = 'fulfilled'//改变状态
        //                 _this.value = value//最终返回值赋值
        //                 console.log(_this.value)
        //             }
        //         }
        //         const reject = function (reason) {
        //             if (_this.state === 'pending') {
        //                 _this.state = 'rejected'//改变状态
        //                 _this.reason = reason//失败原因赋值
        //             }
        //         }
        //         handler(resolve, reject)
        //     }
        // }
        // new _Promise((resolve, reject) => {
        //         resolve(12345)
        // })


        // // 第二版 代码优化,加then方法,模拟异步操作
        // class _Promise {
        //     constructor(handler) {
        //         // 判断参数是否不为函数
        //         if (typeof handler !== 'function') {
        //             throw new TypeError(`${handler} is not a function`)
        //         }
        //         this.initValue()//初始化值
        //         this.bindThis()//绑定this

        //         handler(this.resolve, this.reject)
        //     }
        //     bindThis() {
        //         this.resolve = this.resolve.bind(this)
        //         this.reject = this.reject.bind(this)
        //     }
        //     initValue() {
        //         this.state = 'pending'//初始状态
        //         this.value = null//最终返回值
        //         this.reason = null //失败原因
        //     }
        //     resolve(value) {
        //         if (this.state === 'pending') {
        //             this.state = 'fulfilled'//改变状态
        //             this.value = value//最终返回值赋值
        //         }
        //     }
        //     reject(reason) {
        //         if (this.state === 'pending') {
        //             this.state = 'rejected'//改变状态
        //             this.reason = reason//失败原因赋值
        //         }
        //     }

        //     then(onFulfilled, onRejected) {
        //         if (typeof onFulfilled !== 'function') {
        //             onFulfilled = function (value) {
        //                 return value
        //             }
        //         }

        //         if (typeof onRejected !== 'function') {
        //             onRejected = function (reason) {
        //                 throw reason
        //             }
        //         }

        //         if (this.state === 'fulfilled') {
        //             // 模拟异步
        //             setTimeout(() => {
        //                 onFulfilled(this.value)
        //             }, 1000);
        //         }

        //         if (this.state === 'reject') {
        //             setTimeout(() => {
        //                 onRejected(this.reason)
        //             }, 1000);
        //         }
        //     }
        // }
        // new _Promise((resolve, reject) => {
        //     resolve(1234567)
        // }).then((value) => {
        //     console.log(value, 'value')
        // })
        // new _Promise((resolve, reject) => {
        //     setTimeout(() => {
        //         resolve(1234567)
        //     }, 1000);
        // }).then((value) => {
        //     console.log(value, 'value')
        // })//这种情况下then方法中代码不会打印,因为then方法中state为pending,因此需要添加一个状态判断

        // 第三版 添加状态判断,添加链式调用(then方法需要返回promise对象)
        class _Promise {
            constructor(handler) {
                // 判断参数是否不为函数
                if (typeof handler !== 'function') {
                    throw new TypeError(`${handler} is not a function`)
                }
                this.initValue()//初始化值
                this.bindThis()//绑定this

                try {
                    handler(this.resolve, this.reject)
                } catch (error) {
                    this.reject(error)
                }
            }
            bindThis() {
                this.resolve = this.resolve.bind(this)
                this.reject = this.reject.bind(this)
            }
            initValue() {
                this.state = 'pending'//初始状态
                this.value = null//最终返回值
                this.reason = null //失败原因
                this.onFulfilledCbs = []//成功回调
                this.onRejectedCbs = []//失败回调
            }
            resolve(value) {
                if (this.state === 'pending') {
                    this.state = 'fulfilled'//改变状态
                    this.value = value//最终返回值赋值
                    // resolve成功执行
                    this.onFulfilledCbs.forEach(fn => fn(this.value))
                }
            }
            reject(reason) {
                if (this.state === 'pending') {
                    this.state = 'rejected'//改变状态
                    this.reason = reason//失败原因赋值
                    this.onRejectedCbs.forEach(fn => fn(this.reason))
                }
            }

            then(onFulfilled, onRejected) {
                if (typeof onFulfilled !== 'function') {
                    onFulfilled = function (value) {
                        return value
                    }
                }

                if (typeof onRejected !== 'function') {
                    onRejected = function (reason) {
                        throw reason
                    }
                }

                if (this.state === 'fulfilled') {
                    // 模拟异步
                    setTimeout(() => {
                        onFulfilled(this.value)
                    });
                }

                if (this.state === 'reject') {
                    setTimeout(() => {
                        onRejected(this.reason)
                    });
                }

                let promise2 = new _Promise((resolve, reject) => {
                    if (this.state === 'fulfilled') {
                        setTimeout(() => {
                            try {
                                const data = onFulfilled(this.value)
                                _Promise.resolvePromise(promise2, data, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        })
                    }

                    if (this.state === 'rejected') {
                        setTimeout(() => {
                            try {
                                const data = onRejected(this.reason)
                                _Promise.resolvePromise(promise2, data, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        })
                    }

                    if (this.state === 'pending') {
                        this.onFulfilledCbs.push(value => {
                            setTimeout(() => {
                                try {
                                    const data = onFulfilled(value)
                                    _Promise.resolvePromise(promise2, data, resolve, reject)
                                } catch (e) {
                                    reject(e)
                                }
                            })
                        })

                        this.onRejectedCbs.push(reason => {
                            setTimeout(() => {
                                try {
                                    const data = onRejected(this.reason)
                                    _Promise.resolvePromise(promise2, data, resolve, reject)
                                } catch (e) {
                                    reject(e)
                                }
                            })
                        })
                    }
                })
                return promise2
            }
        }
        _Promise.resolvePromise = function (promise2, data, resolve, reject) {
            // data 与 promise 相等
            if (promise2 === data) {
                reject(new TypeError('Chaining cycle detected for promise'))
            }

            let flag = false
            if (data instanceof _Promise) {
                // 判断 data 为 Promise
                data.then(
                    value => {
                        _Promise.resolvePromise(promise2, value, resolve, reject)
                    },
                    reason => {
                        reject(reason)
                    }
                )
            } else if (data !== null && (typeof data === 'object' || typeof data === 'function')) {
                // data 为对象或函数
                try {
                    const then = data.then
                    if (typeof then === 'function') {
                        then.call(
                            data,
                            value => {
                                if (flag) return
                                flag = true
                                _Promise.resolvePromise(promise2, value, resolve, reject)
                            },
                            reason => {
                                if (flag) return
                                flag = true
                                reject(reason)
                            }
                        )
                    } else {
                        if (flag) return
                        flag = true
                        resolve(data)
                    }
                } catch (e) {
                    if (flag) return
                    flag = true
                    reject(e)
                }
            } else {
                resolve(data)
            }
        }

        new _Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(1234567)
            }, 1000);
        }).then((value) => {
            console.log(value, 'value')
            return 11111
        }, (reason) => {
            console.log(reason, 'reason')
        }).then((res) => {
            console.log(res, 'res')
        })


    </script>
</body>

</html>
原文地址:https://www.cnblogs.com/samsara-yx/p/12217818.html