一、手动实现同步钩子函数
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') });