[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')
});

  

猜你喜欢

转载自www.cnblogs.com/piaobodewu/p/11261408.html