当前位置:   article > 正文

【面试题】手写Promise_面试题手写一个promise代码

面试题手写一个promise代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>手写Promise</title>
</head>
<body>
    <script>
        // 手写 Promise 构造函数
        class MyPromise{
            state = 'pending'   // 状态 'pending' 'fulfilled' 'rejected'
            value = undefined   // 当前 Promise 执行成功后的值
            reason = undefined  // 失败后的原因
            
            resolveCallbacks = []  // pending 状态下,存储成功的回调
            rejectCallbacks = []   // pending 状态下,存储失败的回调


            // 构造函数
            constructor(fn){
                const resolveHandler = (value)=>{
                    if(this.state === 'pending'){
                        this.state = 'fulfilled'
                        this.value = value
                        this.resolveCallbacks.forEach(fn=>fn(this.value))
                    }
                }

                const rejectHandler = (reason)=>{
                    if(this.state === 'pending'){
                        this.state = 'rejected'
                        this.reason = reason
                        this.rejectCallbacks.forEach(fn=>fn(this.reason))
                    }
                }

                try{
                    fn(resolveHandler, rejectHandler)
                }catch(err){
                    rejectHandler(err)
                }
            }

            // then方法
            then(fn1, fn2){
                // 在 pending 状态下,fn1 fn2会被存储到Callbacks中
                fn1 = typeof fn1 === 'function' ? fn1 : (v)=>v
                fn2 = typeof fn2 === 'function' ? fn2 : (e)=>e
                
                if(this.state === 'pending'){
                    const p1 = new MyPromise((resolve, reject)=>{
                        this.resolveCallbacks.push(()=>{
                            try{
                                const newValue = fn1(this.value)
                                resolve(newValue)
                            }catch(err){
                                reject(err)
                            }
                        })
                        this.rejectCallbacks.push(()=>{
                            try{
                                const newReason = fn2(this.reason)
                                reject(newReason)
                            }catch(err){
                                reject(err)
                            }
                        })
                    })
                    return p1
                }

                if(this.state === 'fulfilled'){
                    const p1 = new MyPromise((resolve, reject)=>{
                        try{
                            const newValue = fn1(this.value)
                            resolve(newValue)
                        }catch(err){
                            reject(err)
                        }
                    })
                    return p1
                }
                
                if(this.state === 'rejected'){
                    const p1 = new MyPromise((resolve, reject)=>{
                        try{
                            const newReason = fn2(this.reason)
                            reject(newReason)
                        }catch(err){
                            reject(err)
                        }
                    })
                    return p1
                }
            }

            // catch方法,catch 是 then的一个语法糖,简单模式
            catch(fn){
                return this.then(null, fn)
            }
        }

        // Promise 全局静态的API
        // resolve
        MyPromise.resolve = function(value){
            return new MyPromise((resolve, reject)=>resolve(value))
        }

        // reject
        MyPromise.reject = function(reason){
            return new MyPromise((resolve, reject)=>reject(reason))
        }

        // all  传入Promise数组,等待所有的Promise的状态都 fulfilled 之后,返回一个新的Promise,包含所有结果
        MyPromise.all = function(promiseList = []){
            const p1 = new MyPromise((resolve, reject)=>{
                const result = [];
                const length = promiseList.length
                let resolvedCount = 0   // 用于计数

                promiseList.forEach(p=>{
                    p.then(data=>{
                        result.push(data)
                        // resolvedCount 必须在 then 里面做 ++
                        resolvedCount++
                        if(resolvedCount === length){   // 已经遍历到了最后一个 promise
                            resolve(result)
                        }
                    }).catch(err=>{
                        reject(err)
                    })
                })
            })
            return p1
        }

        // race  传入Promise数组,只要有一个Promise的状态 fulfilled 之后,返回一个新的Promise,包含该Promise结果
        MyPromise.race = function(promiseList = []){
            let resolved = false  // 标记
            const p1 = new MyPromise((resolve, reject)=>{
                promiseList.forEach(p=>{
                    p.then(data=>{
                        if(!resolved){
                            resolve(data)
                            resolved = true
                        }
                    }).catch((err)=>{
                        reject(err)
                    })
                })
            })
            return p1
        }


        //----------------以下是用于测试的代码------------------------------
        
        // 初始化 & 异步调用
        // const p1 = new MyPromise((resolve, reject)=>{
            // 同步
            // resolve(100)   
            // reject('错误信息')
            // 异步 
        //     setTimeout(()=>{   
        //         resolve(100)
        //     }, 1000)
        // })


        // // then catch 链式调用
        // const p11 = p1.then(data1=>{
        //     console.log('data1', data1)
        //     return data1 + 1
        // })
        // const p12 = p11.then(data2=>{
        //     console.log('data2', data2)
        //     return data2 + 2
        // })
        // const p13 = p12.catch(err=>console.error(err))


        // // Promise基本的API  .resolve  .reject  .all   .race
        // const p2 = MyPromise.resolve(200)
        // const p3 = MyPromise.resolve(300)
        // const p4 = MyPromise.reject('错误信息...')
        // const p5 = MyPromise.all([p1, p2, p3])
        // p5.then(result=>console.log('all result', result))
        // const p6 = MyPromise.race([p1, p2, p3])
        // p6.then(result=>console.log('race result', result))
    </script>
</body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/876542
推荐阅读
相关标签
  

闽ICP备14008679号