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

it2022-06-09  70

 

 

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

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

  

 

转载于:https://www.cnblogs.com/piaobodewu/p/11261408.html

相关资源:浅谈Webpack核心模块tapable解析

最新回复(0)