手写Promise实现

140 阅读5分钟

Promise用法

let p = new Promise((resolve, reject) => {
    resolve('success')
})

console.log(p)

let p = new Promise((resolve, reject) => {
    // resolve('success')
    reject('error')
})

console.log(p)

 // then :返还值;1.没有返还 2.返还普通值;3.返还promise对象;
 // 总结:返还promise对象--->链式操作;
 
let p = new Promise((resolve, reject) => {
    resolve('success')
})

let res = p.then(res => {
    // console.log(111)
})

console.log(res)

let p = new Promise((resolve, reject) => {
    resolve('success')
})

let res = p.then(res => {
    return 111
})

console.log(res)

let p = new Promise((resolve, reject) => {
    resolve('success')
})

let res = p.then(res => {
    return new Promise((resolve, reject)=>{
        resolve('111')
    })
})

console.log(res)

手写Promise

原本Promise通过c实现,这里我们用js模拟

let p = new KPromise((resolve, reject) => {
    // 调取的时候通过小括号执行,那么封装的内部会有一个函数
    // 执行函数,并且改变状态和value值
    // resolve('success')
    reject('error')
})

队列里的函数如何依次执行

// axios Promise 中本身也是用这种方式实现

let arr = [function(){
    console.log(1111);
},function(){
    console.log(222);
},function(){
    console.log(3333);
}];
let cb;
while(cb=arr.shift()){
    cb();
}

宏任务微任务

  • js单线程,浏览器多线程。同步任务放入主线程,异步队列放入异步队列。主线程执行完毕后执行异步队列。

  • 微任务:promise;MutationObserver; process.nextTick;

  • 宏任务:setTimeout;setInterval

// 微任务先执行,再宏任务再产生微任务,再执行微任务

// 宏任务
setTimeout(() => {
    console.log('top')
}, 0);

// 原本Promise是微任务,这里模拟是宏任务需要改写成微任务
let p = new KPromise((resolve, reject) => {
    resolve('success111')
    // reject('error111')
})

// 加入队列
p.then(res => {
    console.log(res)
}, err => {
    console.log(err)
})
class KPromise{
    constructor(handle) {
        this.status = 'pending';
        this.value = undefined;

        // 创建异步队列,then 里需要的
        this.resolveQueue = [];
        this.rejectQueue = [];
        handle(this._resolve.bind(this), this._reject.bind(this))
    }
    _resolve(val){
        this.status = 'resolved'
        this.value = val

        // 执行then里成功的回调
        let run = () => {
            let cb;
            // console.log(this.resolveQueue)  Obj无length
            while(cb = this.resolveQueue.shift()) {
                cb(val)
            }
        }
        setTimeout(run, 0)
        
    }
    _reject(err) {
        this.status = 'rejected'
        this.value = err

        // 执行then里失败的回调
        let run = () => {
            let cb;
            while(cb = this.rejectQueue.shift()) {
                cb(err)
            }
        }
        setTimeout(run, 0)

    }
    // 把多个onResolved 及 onRejected放在队列里
    then(onResolved, onRejected){
        this.resolveQueue.push(onResolved)
        this.rejectQueue.push(onRejected)
    }
}

MutationObserver
let observer = new MutationObserver(function(){
    console.log("微任务回调");
})
// 有属性变化会触发回调
observer.observe(document.body,{
    attributes: true
})
document.body.setAttribute("kkb",Math.random());

改写成与Promise一致
class KPromise{
    constructor(handle) {
        this.status = 'pending';
        this.value = undefined;

        // 创建异步队列,then 里需要的
        this.resolveQueue = [];
        this.rejectQueue = [];
        handle(this._resolve.bind(this), this._reject.bind(this))
    }
    _resolve(val){
        // console.log(this) undefinded
        this.status = 'resolved'
        this.value = val

        // 执行then里成功的回调
        let run = () => {
            let cb;
            // console.log(this.resolveQueue)  Obj无length
            while(cb = this.resolveQueue.shift()) {
                cb(val)
            }
        }
        let observer = new MutationObserver(run)

        observer.observe(document.body, {
            attributes: true
        })

        document.body.setAttribute('kkb', Math.random())
    }
    _reject(err) {
        this.status = 'rejected'
        this.value = err

        // 执行then里失败的回调
        let run = () => {
            let cb;
            while(cb = this.rejectQueue.shift()) {
                cb(err)
            }
        }
        setTimeout(run, 0)

    }
    // 把多个onResolved 及 onRejected放在队列里
    then(onResolved, onRejected){
        this.resolveQueue.push(onResolved)
        this.rejectQueue.push(onRejected)
    }
}

then 创建队列
创建队列,执行先后导致队列为空
// 这样写会有问题,先执行了回调后加入队列
// this.resolveQueue 为 [ ]

let p = new KPromise((resolve, reject) => {
    // 调取的时候通过小括号执行,那么封装的内部会有一个函数
    // 执行函数,并且改变状态和value值
    resolve('success111')
    // 执行了回调
    
    // reject('error111')
})

// 加入队列
p.then(res => {
    console.log(res)
}, err => {
    console.log(err)
})
class KPromise{
    constructor(handle) {
        this.status = 'pending';
        this.value = undefined;

        // 创建异步队列,then 里需要的
        this.resolveQueue = [];
        this.rejectQueue = [];
        handle(this._resolve.bind(this), this._reject)
    }
    // 错误语法
    // () => {

    // }
    _resolve(val){
        // console.log(this) undefinded
        this.status = 'resolved'
        this.value = val

        console.log(this.resolveQueue)  // [ ] 
        // 执行then里成功的回调
        let run = () => {
            let cb;
            while(cb = this.resolveQueue.shift()) {
                cb(val)
            }
        }
        // run()
        // setTimeout(run, 0)
        
    }
    _reject(err) {
        this.status = 'rejected'
        this.value = err
        // 执行then里失败的回调
    }
    // 把多个onResolved 及 onRejected放在队列里
    then(onResolved, onRejected){
        this.resolveQueue.push(onResolved)
        this.rejectQueue.push(onRejected)
    }
}
修改后的js
// 修改后的js,执行回调需要放到setTimeout中

class KPromise{
    constructor(handle) {
        this.status = 'pending';
        this.value = undefined;

        // 创建异步队列,then 里需要的
        this.resolveQueue = [];
        this.rejectQueue = [];
        handle(this._resolve.bind(this), this._reject)
    }
    _resolve(val){
        this.status = 'resolved'
        this.value = val

        // 执行then里成功的回调
        let run = () => {
            let cb;
            // console.log(this.resolveQueue)  Obj无length
            while(cb = this.resolveQueue.shift()) {
                cb(val)
            }
        }
        setTimeout(run, 0)
        
    }
    _reject(err) {
        this.status = 'rejected'
        this.value = err

        // 执行then里失败的回调
        let run = () => {
            let cb;
            while(cb = this.rejectQueue.shift()) {
                cb(err)
            }
        }
        setTimeout(run, 0)

    }
    // 把多个onResolved 及 onRejected放在队列里
    then(onResolved, onRejected){
        this.resolveQueue.push(onResolved)
        this.rejectQueue.push(onRejected)
    }
}

全部代码

    // 宏任务
    // setTimeout(() => {
    //     console.log('top')
    // }, 0);
    // // 微任务
    // let p = new KPromise((resolve, reject) => {
    //     // 调取的时候通过小括号执行,那么封装的内部会有一个函数
    //     // 执行函数,并且改变状态和value值
    //     // resolve('success111')
    //     // 执行了回调
    //     reject('error111')
    // })

    // // 加入队列
    // p.then(res => {
    //     console.log(res)
    // }, err => {
    //     console.log(err)
    // })

    // p.then(res => {
    //     console.log(res)
    // }, err => {
    //     console.log(err)
    // })
    // console.log(p)


    // 链式调用:then始终返回promise对象
    // let response = p.then(res=>{
    //     return res
    //     // console.log("1",res)
    //     // return new KPromise((resolve, reject)=>{
    //     //     resolve('111')
    //     // })
    // }, err => {
    //     // console.log(err)
    // })
    // console.log(response)

    // let p1 = KPromise.resolve('111')
    // console.log(p1)

    // let p2 = KPromise.reject('error')
    // console.log(p2)

    // let p1 = new KPromise((resolve) => {
    //     resolve(111)
    // })
    // let p2 = new KPromise((resolve) => {
    //     resolve(222)
    // })

    // KPromise.all([p1, p2]).then(res => {
    //     console.log(res)
    // })

    // KPromise.race([p1, p2]).then(res => {
    //     console.log(res)
    // })
    // console.log(p3)

    let p = new KPromise((resolve,reject)=>{
        reject("err...");
    })
    p.then(res=>{
        console.log(res);
    }).catch(err=>{
        console.log(err);
    })
    // console.log(p)
class KPromise{
    constructor(handle) {
        this.status = 'pending';
        this.value = undefined;

        // 创建异步队列,then 里需要的
        this.resolveQueue = [];
        this.rejectQueue = [];
        handle(this._resolve.bind(this), this._reject.bind(this))
    }
    // 错误语法
    // () => {

    // }
    _resolve(val){
        // console.log(val)
        // console.log(this) undefinded
        this.status = 'resolved'
        this.value = val
        // console.log(val)

        // 执行then里成功的回调
        let run = () => {
            let cb;
            // console.log(this.resolveQueue)  Obj无length
            while(cb = this.resolveQueue.shift()) {
                cb(val)
            }
        }
        let observer = new MutationObserver(run)

        observer.observe(document.body, {
            attributes: true
        })

        document.body.setAttribute('kkb', Math.random())
        // setTimeout(run, 0)
        
    }
    _reject(err) {
        this.status = 'rejected'
        this.value = err
        // console.log(err)

        // 执行then里失败的回调
        let run = () => {
            let cb;
            while(cb = this.rejectQueue.shift()) {
                cb(err)
            }
        }

        let observer = new MutationObserver(run)

        observer.observe(document.body, {
            attributes: true
        })
        document.body.setAttribute('kkb', Math.random())
        // setTimeout(run, 0)

    }
    // then :返还值;1.没有返还 2.返还普通值;3.返还promise对象; 总结:返还promise对象--->链式操作;
    // 把多个onResolved 及 onRejected放在队列里
    then(onResolved, onRejected){
        // console.log(onResolved)
        /**
         * onResolved 接收传入的函数
         * 
          (res)=>{
            // return res
            // console.log("1",res)
            return new KPromise((resolve, reject)=>{
                resolve('111')
            })
        }
         */

       // this.resolveQueue.push(onResolved)
        // this.rejectQueue.push(onRejected)
        return new KPromise((resolve, reject) => {
            this.resolveQueue.push(val => {
                // console.log(val)

                // 要拿到value onResolved 必须执行,执行后如果return 了Promise对象,那么val instanceof KPromise
                // val 为then 第一个参数的执行结果,需要重新被赋值
                /**
                 *  无return 时,promise value 为undefined
                 *  return res时,return 传入的val
                 *  
                 *  return promise 时 return val.then(resolve)
                 */
                let val1 = onResolved && onResolved(val)
                // console.log(onResolved && onResolved(val))

                // 如果then返还的是Promise对象
                if(val1 instanceof KPromise) {

                    // return val 返回的是80行的kPromise, 再调取then
                    return val1.then(resolve)
                }
                // 普通值直接返还
                resolve(val1)
            })

            this.rejectQueue.push(err => {
                onRejected && onRejected(err)
                reject(err)
            })
        })
    }
    static resolve(val) {
        return new KPromise(resolve => {
            resolve(val)
        })
    }
    static reject(err) {
        return new KPromise((resolve, reject) => {
            reject(err)
        })
    }
    static all(lists) {
        return new KPromise((resolve, reject) => {
            let arr = []
            for(let i = 0; i < lists.length; i++) {
                lists[i].then(res => {
                    console.log(res)
                    arr.push(res)
                }, err => {
                    reject(err)
                })
            }
            resolve(arr)
        })
    }
    static race(lists) {
        return new KPromise((resolve, reject) => {
            for(let i = 0; i < lists.length; i++) {
                lists[i].then(res => {
                    resolve(res)
                }, err => {
                    reject(err)
                })
            }
        })
    }
    catch(onRejected) {
        console.log(onRejected)
        this.then(undefined, onRejected)
    }
}