zoukankan      html  css  js  c++  java
  • [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')
    });
    

      

  • 相关阅读:
    虚函数和纯虚函数
    MS CRM 2011中PartyList类型字段的实例化
    MS CRM 2011的自定义与开发(12)——表单脚本扩展开发(4)
    MS CRM 2011的自定义与开发(12)——表单脚本扩展开发(2)
    MS CRM 2011的自定义和开发(10)——CRM web服务介绍(第二部分)——IOrganizationService(二)
    MS CRM 2011 SDK 5.08已经发布
    MS CRM 2011 Q2的一些更新
    最近很忙
    Microsoft Dynamics CRM 2011最近的一些更新
    补一篇,Update Rollup 12 终于发布了
  • 原文地址:https://www.cnblogs.com/piaobodewu/p/11261408.html
Copyright © 2011-2022 走看看