webpack 模拟Tapable实现AsyncSeriesHook钩子

in JavaScript with 0 comment

AsyncSeriesHook

AsyncSeriesHook 钩子函数实现的是串行任务,每个任务返回值都是promise, 它能实现先添加的任务先执行,并且前一个任务要成功resolve,才执行后一个任务,所有任务都resolve后执行最终的then()回调

现在来模拟一下

要执行的任务代码

tap(){
        // 订阅消息
        this.hooks.vue.tapPromise("zs", (des) => {
            return new Promise(function (resolve, reject) {
                setTimeout(function () {
                    console.log("zs", des);
                    resolve();
                }, 3000);
            })
        });
        this.hooks.vue.tapPromise("ls", function (des, cb) {
            return new Promise(function (resolve, reject) {
                setTimeout(function () {
                    console.log("ls", des);
                    resolve();
                }, 2000);
            })
        });
        this.hooks.vue.tapPromise("ww", function (des, cb) {
            return new Promise(function (resolve, reject) {
                setTimeout(function () {
                    console.log("ww", des);
                    resolve();
                }, 1000);
            })
        });
    }
    call(){
        // 发布消息
        this.hooks.vue.promise("vue课程上线了").then(function () {
            console.log("end");
        });
    }

执行这个任务

promise(...args){
        if(args.length < this.args.length){
            return new Error("参数个数不对");
        }
        args = args.slice(0, this.args.length + 1);
        let [firstTask, ...others] = this.tasks;
        //核心工具reduce
        return others.reduce(function (promise, task) {
            return promise.then(()=>{
                return task(...args);
            });
        }, firstTask(...args));
    }

这里用到的es6的reduce()函数,核心代码就是这个reduce,现在来分析一下整个reduce的执行过程

首先对promise的返回值与promise的嵌套搞了一个demo

 //Promise.resolve() 返回值也是promise, [[PromiseState]]: "fulfilled",  [[PromiseResult]]: "hello"
    //Promise.resolve().then() 返回值也是promise, [[PromiseState]]: "fulfilled",  [[PromiseResult]]: "hello"
    // let res = Promise.resolve('hello').then()
    // console.log(res)
    let myPromise = new Promise((resolve, reject) => {
      resolve('myPromise')
    })
    //这里更容易看出, myPromise.then()返回的是一个Promise
    //如果没有resolve, 打印[[PromiseState]]: "pending", [[PromiseResult]]: undefined
    //如果resolve()了,则打印[[PromiseState]]: "fulfilled", [[PromiseResult]]: undefined
    let newPromise = new Promise((resolve, reject) => {
        resolve('newPromise')
    })
     let res = myPromise.then((val) => {
        //return val
        //这里能明显看出,如果return val则返回的res是myPromse这个实例
        //如果内部再返回一个newPromise,则返回的res是这个内部的newPromise实例
       return newPromise
     })
     console.log(res)

分析上边核心代码reduce()的执行流程

//这里分析firstTasks(...args),如果这个promise没有resolve,则这个promise作为最终的返回值返回给外界 ress,输出'zs'
//如果resolve了,则执行then(),这时firstTasks(...args)返回的promise就不作为最终的返回值返回给外界ress了
//执行then() 则输出 'i am resolved',然后return 第二个任务的promise,现在情况是外层是第一个promise,内层返回了第二个promise
//当两个promise嵌套的时候会返回内层的promise,见以上demo分析
//现在的情况是这个内层的promise去哪了?
//1 返回给外界ress, 2 赋值给promiset
//猜测是赋值给promiset, 这是reduce正常迭代过程,输出 'ls'
//分析 如果这个promiset 没有 resolve ,则第二个promise直接返回给外界了
//如果这个promiset resolve 了,则 输出 'i am resolved',然后把第三个promise返回了,给到参数promiset
//前两次每次返回promise赋值给promiset形参后,都是执行return promiset.then() 进行判断, 输出 'ww'
//但最后一次,由于数组任务递归完毕,这一次不会再运行return promiset.then() 了,而是把第三个promise直接返回给了外界ress
//如果最后一次promise resolve了,则输出整个的then,如果没有resolve,就不会执行最终的then()代码

评论已关闭.