• [webpack]深入学习webpack核心模块tapable


    一、手动实现同步钩子函数

    1、SyncHook

    class SyncHook {
        // 钩子是同步的
        constructor(args){
            this.tasks = [];
        }
        tap(name,task){
            this.tasks.push(task)
        }
        call(...args){
            this.tasks.forEach(
                (task)=>task(...args)
            )
        }
    }
    
    // 绑定事件就是订阅
    let hook = new SyncHook(['name']);
    
    hook.tap('react',function (name) {
        console.log('react',name)
    });
    hook.tap('node',function (name) {
        console.log('node',name)
    });
    
    hook.call('dellyoung');
    

     

    2、SyncWaterfallHook

    class SyncWaterfallHook {
        // 钩子是同步的
        constructor(args){
            this.tasks = [];
        }
        tap(name,task){
            this.tasks.push(task)
        }
        call(...args){
            let [first,...others] = this.tasks;
            let ret = first(...args);
            others.reduce(
                (a,b)=>{
                    // a 上一个 b 下一个
                    return b(a);
                },ret
            )
        }
    }
    
    // 绑定事件就是订阅
    let hook = new SyncWaterfallHook(['name']);
    
    hook.tap('react',function (name) {
        console.log('react1',name);
        return 'reactOk'
    });
    
    hook.tap('node',function (name) {
        console.log('node2',name);
        return 'nodeOk'
    });
    
    hook.tap('webpack',function (name) {
        console.log('webpack',name)
    });
    
    hook.call('dellyoung');
    

     

    3、SyncLoopHook

    class SyncLoopHook {
        // 钩子是同步的
        // 只要返回不是undefined就会一直循环
        constructor(args){
            this.tasks = [];
        }
        tap(name,task){
            this.tasks.push(task)
        }
        call(...args){
            this.tasks.forEach(
                task=>{
                    let ret;
                    do {
                        ret = task(...args)
                    }while (ret !== undefined)
                }
            )
        }
    }
    
    // 绑定事件就是订阅
    let hook = new SyncLoopHook(['name']);
    let total = 0;
    
    hook.tap('react',function (name) {
        console.log('react',name);
        return ++total === 3?undefined:'继续学'
    });
    
    hook.tap('node',function (name) {
        console.log('node',name);
    });
    
    hook.tap('webpack',function (name) {
        console.log('webpack',name)
    });
    
    hook.call('dellyoung');
    

     

    4、SyncBailHook

    class SyncBailHook {
        // 钩子是同步的
        constructor(args){
            this.tasks = [];
        }
        tap(name,task){
            this.tasks.push(task)
        }
        call(...args){
            let ret; // 当前函数返回值
            let index=0; // 先执行第一个
            do{
                ret = this.tasks[index++](...args)
            }while (ret === undefined && index < this.tasks.length);
        }
    }
    
    // 绑定事件就是订阅
    let hook = new SyncBailHook(['name']);
    
    hook.tap('react',function (name) {
        console.log('react1',name);
        // return '停止'
    });
    hook.tap('node',function (name) {
        console.log('node2',name)
    });
    
    hook.call('dellyoung');
    

      

    二、手动实现异步钩子函数

    1、AsyncParallelBailHook

    类似promise.all[]

    class AsyncParallelBailHook {
        // 钩子是同步的
        // 只要返回不是undefined就会一直循环
        constructor(args){
            this.tasks = [];
        }
        tapAsync(name,task){
            this.tasks.push(task)
        }
        callAsync(...args){
            let finalCallBack  = args.pop(); // 拿出最终的函数
            let index = 0;
            let done = () => {
                index++;
                if(index === this.tasks.length){
                    finalCallBack();
                }
            };
            this.tasks.forEach(task=>{
                task(...args,done)
            })
        }
    }
    
    // 绑定事件就是订阅
    let hook = new AsyncParallelBailHook(['name']);
    
    hook.tapAsync('react',function (name,callback) {
        setTimeout(()=>{
                console.log('react',name);
                callback();
            },5000
        );
    });
    
    hook.tapAsync('node',function (name,callback) {
        setTimeout(()=>{
                console.log('node',name);
                callback();
            },1000
        );
    });
    
    hook.callAsync('dellyoung',function () {
        console.log('newBegin')
    });
    

    promise版本的AsyncParallelBailHook

    class AsyncParallelBailHook {
        // 钩子是同步的
        // 只要返回不是undefined就会一直循环
        constructor(args) {
            this.tasks = [];
        }
    
        tabPromise(name, task) {
            this.tasks.push(task)
        }
    
        promise(...args) {
            let tasks = this.tasks.map(
                (task) => {
                    return task(...args)
                }
            );
            // let tasks = this.tasks.map(task => task(...args));
            return Promise.all(tasks);
        }
    }
    
    // 绑定事件就是订阅
    let hook = new AsyncParallelBailHook(['name']);
    
    hook.tabPromise('react', function (name) {
        return new Promise(
            (resolve, reject) => {
                setTimeout(() => {
                        console.log('react', name);
                        resolve();
                    }, 1000
                );
            }
        )
    });
    
    hook.tabPromise('node', function (name) {
        return new Promise(
            (resolve, reject) => {
                setTimeout(() => {
                        console.log('node', name);
                        resolve();
                    }, 2000
                );
            }
        )
    });
    
    hook.promise('dellyoung').then(function () {
        console.log('newBegin')
    });
    

    2、AsyncSeriesHook

    异步串行

    class AsyncSeriesHook {
        constructor(args) {
            this.tasks = [];
        }
    
        tabAsync(name, task) {
            this.tasks.push(task)
        }
    
        callAsync(...args) {
            let finalCallBack = args.pop();
            let index = 0;
            let next = () => {
                if(this.tasks.length === index){
                    return finalCallBack();
                }
                let task = this.tasks[index++];
                task(...args, next);
            };
            next();
        }
    }
    
    // 绑定事件就是订阅
    let hook = new AsyncSeriesHook(['name']);
    
    hook.tabAsync('react', function (name, callback) {
        setTimeout(() => {
                console.log('react', name);
                callback();
            }, 3000
        );
    });
    
    hook.tabAsync('node', function (name, callback) {
        setTimeout(() => {
                console.log('node', name);
                callback();
            }, 1000
        )
    });
    
    hook.callAsync('dellyoung',function () {
        console.log('newBegin')
    });

    promise版本的AsyncSeriesHook 

    class AsyncSeriesHook {
        constructor(args) {
            this.tasks = [];
        }
    
        tabPromise(name, task) {
            this.tasks.push(task)
        }
    
        promise(...args) {
            // 类redux源码
            let [first,...other] = this.tasks;
            return other.reduce(
                (prom,n)=>{
                    return prom.then(()=>n(...args))
                },first(...args)
            )
        }
    }
    
    // 绑定事件就是订阅
    let hook = new AsyncSeriesHook(['name']);
    
    hook.tabPromise('react', function (name) {
        return new Promise(
            (resolve, reject) => {
                setTimeout(() => {
                        console.log('react', name);
                        resolve();
                    }, 1000
                );
            }
        )
    });
    
    hook.tabPromise('node', function (name) {
        return new Promise(
            (resolve, reject) => {
                setTimeout(() => {
                        console.log('node', name);
                        resolve();
                    }, 1000
                );
            }
        )
    });
    
    hook.promise('dellyoung').then(function () {
        console.log('newBegin')
    });
    

      

     3、AsyncSeriesWaterfallHook

    异步瀑布串行

    class AsyncSeriesWaterfallHook {
        constructor(args) {
            this.tasks = [];
        }
    
        tapAsync(name, task) {
            this.tasks.push(task)
        }
    
        callAsync(...args) {
            let finalCb = args.pop();
            let index = 0;
            let next = (err,data) => {
                let task = this.tasks[index];
                if(!task) return finalCb();
                if(err) return ;
                if(index===0){
                    // 执行第一个
                    task(...args,next)
                }else {
                    task(data,next)
                }
                index++;
            };
            next()
        }
    }
    
    // 绑定事件就是订阅
    let hook = new AsyncSeriesWaterfallHook(['name']);
    
    hook.tapAsync('react', function (name, cb) {
        setTimeout(() => {
                console.log('react', name);
                cb(null, 'result1');
            }, 1000
        );
    });
    
    hook.tapAsync('node', function (data, cb) {
        setTimeout(() => {
                console.log('node', data);
                cb(null);
            }, 2000
        );
    });
    
    hook.callAsync('dellyoung',function () {
        console.log('newBegin')
    });
    

      

  • 相关阅读:
    仿QQ信息弹出
    天高云淡 leobbs皮肤
    http://www.xywq.com/files/ganzhi11.htm
    用Silverlight打造位运算器(3)--完成
    用Silverlight打造位运算器(1)--制作简易工具条控件
    用Silverlight打造位运算器(2)--制作数字文本框控件
    Lucky Sequence[SRM403DIVI500]
    答复:“判断一个整数的二进制位中有多少个1”的提问
    Python 笔记(1)
    #define中的#、## && #@
  • 原文地址:https://www.cnblogs.com/piaobodewu/p/11261408.html
Copyright © 2020-2023  润新知