• 手写promise


    实现目标

    • 定义promise构造函数
    • 实现then方法
    • then方法的链式调用
    • 实现catch方法
    • 实现finally方法
    • 实现resolve静态方法
    • 实现all静态方法

    代码

    class MPromise {
        constructor(handler) {
            // 保存promise的状态
            this.status = 'PENDING'
            // 将then()中resolve方法加入到队列中,当执行promise状态变为“成功态”后调用
            this.resolveHandlers = []
            this.rejectHandlers = []
            // 保存finally()回调函数,当promise状态改变后调用
            this.finallyHandlers = []
            // 将_resolve()中的this指向绑定到当前实例对象
            handler(this._resolve.bind(this), this._reject.bind(this))
        }
    
        _resolve(val) {
            // 状态改变后,不能再执行
            if (this.status != 'PENDING') return
            this.status = 'FULFILLED'
    
            this._observer(() => {
                // 状态改变后,从事件队列(FIFO)中获取循环获取事件执行
                let handler;
                while (handler = this.resolveHandlers.shift()) {
                    handler(val)
                }
                while (handler = this.finallyHandlers.shift()) {
                    handler(val)
                }
            })
        }
    
        _reject(val) {
            if (this.status != 'PENDING') return
            this.status = 'REJECTED'
    
            this._observer(() => {
                let handler;
                while (handler = this.rejectHandlers.shift()) {
                    handler(val)
                }
                while (handler = this.finallyHandlers.shift()) {
                    handler(val)
                }
            })
        }
    
        // 将事件对象放入到MutationObserver微任务中,目的是保证then()中事件先于setTimeout等宏任务执行
        _observer(callback) {
            let observer = new MutationObserver(() => {
                callback()
                observer.disconnect()
            })
            observer.observe(document.body, {
                attributes: true
            })
            document.body.setAttribute('mb', Math.random())
        }
    
        then(resolveCb, rejectCb) {
            return new MPromise((resolve, reject) => {
                if (resolveCb && typeof resolveCb == "function") {
                    // 将resolve事件放入到resolve队列中,目的是保证promise状态改变为“成功态”后,再执行
                    this.resolveHandlers.push(val => {
                        // 链式调用时,获取resolve事件返回值,并传入到下次then()中
                        val = resolveCb(val)
                        if (val && val instanceof MPromise) {
                            return val.then(resolve, reject)
                        }
                        resolve(val)
                    })
                }
                if (rejectCb && typeof rejectCb == "function") {
                    this.rejectHandlers.push(val => {
                        val = rejectCb(val)
                        if (val && val instanceof MPromise) {
                            return val.then(resolve, reject)
                        }
                        reject(val)
                    })
                }
            })
        }
    
        // 类似于then()中的第二个参数
        catch(cb) {
            return this.then(null, cb)
        }
    
        // 不能立即执行,放入事件队列中,等待promise状态改变后再执行
        finally(cb) {
            this.finallyHandlers.push(cb)
        }
    
        static resolve(val) {
            return new MPromise(resolve => {
                resolve(val)
            })
        }
    
        static all(it) {
            let len = it.length
            return new MPromise(resolve => {
                let vals = []
                let n = 0
                for (let i = 0; i < len; i++) {
                    it[i].then(val => {
                        // 保证返回数组中顺序和promise一致
    
                        vals[i] = val
                        n++
                        // 当数组中promise对象全部执行完成后,再调用resolve()
                        if (n == len) {
                            resolve(vals)
                        }
                    })
                }
            })
        }
    }
    

    测试

    实现promise构造函数
    /**
     *  1. 构造函数内部代码立即执行
     *  2. 构造函数一个方法,方法中接受两个函数作为参数
     *      - resolve:将promise状态变为“成功态”
     *      - reject:将promise状态变为“失败态”
     *  3. promise状态一旦改变就不能再次更改
     */
    let p = new MPromise((resolve, reject) => {
        console.log("promise")
        
        resolve(100)
        // reject('error')
    })
    
    实现then方法
    /**
     *  1. 接受两个回调函数作为参数
     *      - 第一个参数:promise状态变为“成功”时调用
     *      - 第二个参数:promise状态变为“失败”时调用
     *  2. 回调函数中可接受调用resolve()、reject()方法时,传递的参数
     *  3. then()中执行顺序先于setTimeout异步函数
     */
    console.log('1111')
    setTimeout(() => {
        console.log("外部setTimeout执行")
    })
    
    let p = new MPromise((resolve, reject) => {
        console.log("promise")
        resolve(100)
    })
    p.then(res => {
        console.log('then方法中的返回值:', res)
    }, err => {
        console.log('then方法中返回的错误:', err)
    })
    
    then方法的链式调用
    /**
     *  1. then方法返回一个promise对象,可实现方法的链式调用
     *  2. then方法接受参数函数中,可返回值/Promise对象作为再次then()回调函数的参数
     *      - 返回值:封装为promise对象返回
     *      - 返回promise对象:调用then()后返回
     * 
     */
    let p = new MPromise((resolve, reject) => {
        console.log("promise")
        resolve(100)
    })
    p.then(res => {
        console.log('then方法中的返回值:', res)
        // return 200
        return new MPromise((resolve, reject) => {
            resolve(200)
        })
    }).then(res => {
        console.log("第二次then方法中的返回值:", res)
    })
    
    实现catch方法
    /**
     *  1. 只实现了捕获调用reject()的错误,未实现new Error()中的错误
     *  2. 回调函数中可接受调用reject()方法时,传递的参数
     */
    let p = new MPromise((resolve, reject) => {
        console.log("promise")
        resolve(100)
    })
    p.then(res => {
        console.log('then方法中的返回值:', res)
        return new MPromise((resolve, reject) => {
            reject('error')
        })
    }).catch(err => {
        console.log('catch中捕获的错误:', err)
    })
    
    实现finally方法
    /**
     *  1. 接受回调函数作为参数,promise状态改变后执行
     */
     let p = new MPromise((resolve, reject) => {
        console.log("promise")
        resolve(100)
    })
    p.then(res => {
        console.log('then方法中的返回值:', res)
        return new MPromise((resolve, reject) => {
            reject('error')
        })
    }).catch(err => {
        console.log('catch中捕获的错误:', err)
    }).finally(() => {
        console.log('执行finally')
    })
    
    实现resolve静态方法
    /**
     *  1. 返回一个“成功态”的promise对象
     */
    let p = MPromise.resolve(100)
    console.log(p)
    
    实现all静态方法
    /**
     *  1. 接受一个promise数组
     *  2. 数组中promise全部调用完成后,返回一个包含promise数组结果的promise对象
     */
    let p1 = new MPromise((resolve, reject) => {
        setTimeout(() => {
            resolve(100)
        }, 500)
    })
    let p2 = new MPromise((resolve, reject) => {
        setTimeout(() => {
            resolve(200)
        }, 1000)
    })
    let p3 = new MPromise((resolve, reject) => {
        setTimeout(() => {
            resolve(300)
        }, 100)
    })
    MPromise.all([p1, p2, p3]).then(vals => {
        console.log(vals)
    })
    
  • 相关阅读:
    js伪数组转数组内部实现
    Vuex核心部分学习参考地址
    vue中让异步代码变成同步的写法
    node.js中文件操作路径和模板标识路径问题
    如果不想安装cnpm又想使用淘宝的服务器来下载,怎么做?
    npm常用命令
    node中模块加载机制
    通过nodejs,简单模拟客户端和服务端进行通信
    vue中非父子组件的传值
    图论1-2
  • 原文地址:https://www.cnblogs.com/mengbing/p/16141792.html
Copyright © 2020-2023  润新知