Tapable 类似于 emimt ,是一个专注于事件流的库。tapable 还允许通过回调参数访问事件的发起者和响应者。

内部支持9种类型的执行hook

  1. const {
  2. SyncHook, //串行执行, 不关心返回值。
  3. SyncBailHook,//串行执行,有一个返回值不为null ,则停止执行后续事件。
  4. SyncWaterfallHook,// 串行执行,返回值会被传递,并被加起来。
  5. SyncLoopHook,//串行循环执行,只要还有一个返回值是 undefined 就会持续循环全部事件,直到最后一个返回值为no-undefined则立即结束。
  6. AsyncParallelHook,//并行执行
  7. AsyncParallelBailHook,
  8. AsyncSeriesHook,
  9. AsyncSeriesBailHook,
  10. AsyncSeriesWaterfallHook
  11. } = require("tapable");

Async

SyncHook

串行执行, 不关心返回值。

  1. var {SyncHook} = require("tapable")
  2. const hook = new SyncHook(["name", "age"]);
  3. hook.tap('1',(name,age)=>{
  4. console.log(name,1)
  5. })
  6. hook.tap('2',(name,age)=>{
  7. console.log(name,2)
  8. })
  9. hook.call('GMX')
  10. //"GMX" 1
  11. //"GMX" 2

SyncBailHook

串行执行,有一个返回值不为undefined,则停止执行后续事件。

  1. var tapable = require("tapable")
  2. const hook = new tapable.SyncBailHook(["name", "age"]);
  3. hook.tap('1',(name,age)=>{
  4. console.log(name+1)
  5. return 'GG'
  6. })
  7. hook.tap('2',(name,age)=>{
  8. console.log(name+2)
  9. })
  10. console.log('return:' + hook.call('GMX'))
  11. //"GMX1"
  12. //"return:GG"

SyncWaterfallHook

串行执行,返回值会被传递,并被加起来。

  1. var tapable = require("tapable")
  2. const hook = new tapable.SyncWaterfallHook(["name", "age"]);
  3. hook.tap('1',(name,age)=>{
  4. console.log(name+1)
  5. return 1
  6. })
  7. hook.tap('2',(name,age)=>{
  8. console.log(name+2)
  9. return 2
  10. })
  11. console.log('return:' + hook.call('GMX'))
  12. //GMX1
  13. //3
  14. //return:2

SyncLoopHook

串行循环执行,循环执行所有返回值不为 undefined 的事件,直到所有返回值都是undefined。

  1. var tapable = require("tapable")
  2. var count = 0;
  3. const hook = new tapable.SyncLoopHook(["name", "age"]);
  4. hook.tap('1',(name,age,res)=>{
  5. console.log(name+'_'+count+'_'+1)
  6. if(count > 2){
  7. return undefined
  8. }
  9. count ++
  10. return 1
  11. })
  12. hook.tap('2',(name,age,res)=>{
  13. console.log(name+'_'+count+'_'+2)
  14. if(count > 3){
  15. return undefined
  16. }
  17. count ++
  18. return 2
  19. })
  20. hook.tap('3',(name,age,res)=>{
  21. console.log(name+'_'+count+'_'+2)
  22. if(count > 4){
  23. return undefined
  24. }
  25. count ++
  26. return 3
  27. })
  28. console.log('return:' + hook.call('GMX'))
  29. //GMX_0_1
  30. //GMX_1_1
  31. //GMX_2_1
  32. //GMX_3_1
  33. //GMX_3_2
  34. //GMX_4_1
  35. //GMX_4_2
  36. //GMX_4_2
  37. //GMX_5_1
  38. //GMX_5_2
  39. //GMX_5_2
  40. //return:undefined

Async

async 异步事件支持两种事件模式,callback + promise。

AsyncParallelHook

并行异步执行,第一个事件回调之后,就会调用总的回调,但是事件会执行完成。返回第一个执行完成的值。

  1. var tapable = require("tapable")
  2. const hook = new tapable.AsyncParallelHook(["name", "age"]);
  3. hook.tapAsync('3',(name,age,callback)=>{
  4. setTimeout(()=>{
  5. console.log(name+3)
  6. callback('c3')
  7. },3000)
  8. })
  9. hook.tapAsync('1',(name,age,callback)=>{
  10. setTimeout(()=>{
  11. console.log(name+1)
  12. callback('c1')
  13. },1000)
  14. })
  15. hook.tapAsync('2',(name,age,callback)=>{
  16. setTimeout(()=>{
  17. console.log(name+2)
  18. callback('c2')
  19. },2000)
  20. })
  21. hook.callAsync('GMX','18',(res)=>{
  22. console.log('res:'+res);
  23. })
  24. //"GMX1"
  25. //"res:c1"
  26. //"GMX2"
  27. //"GMX3"

AsyncParallelBailHook

并行异步执行,等待所有都执行完成才会回调结束。返回最后一个值。

  1. var tapable = require("tapable")
  2. const hook = new tapable.AsyncParallelBailHook(["name", "age"]);
  3. hook.tapPromise('3',(name,age)=>{
  4. return new Promise((reslove,reject)=>{
  5. setTimeout(()=>{
  6. console.log(name+3)
  7. reslove('c3')
  8. },3000)
  9. })
  10. })
  11. hook.tapPromise('1',(name,age)=>{
  12. return new Promise((reslove,reject)=>{
  13. setTimeout(()=>{
  14. console.log(name+1)
  15. reslove('c1')
  16. },1000)
  17. })
  18. })
  19. hook.tapPromise('2',(name,age)=>{
  20. return new Promise((reslove,reject)=>{
  21. setTimeout(()=>{
  22. console.log(name+2)
  23. reslove('c2')
  24. },2000)
  25. })
  26. })
  27. hook.promise('GMX','18').then((res)=>{
  28. console.log('res:'+res);
  29. })
  30. //"GMX1"
  31. //"GMX2"
  32. //"GMX3"
  33. //"res:c3"

AsyncSeriesHook

串行异步执行,所有都执行结束后返回,无返回值。

  1. var tapable = require("tapable")
  2. const hook = new tapable.AsyncSeriesHook(["name", "age"]);
  3. hook.tapPromise('3',(name,age)=>{
  4. return new Promise((reslove,reject)=>{
  5. setTimeout(()=>{
  6. console.log(name+3)
  7. reslove('c3')
  8. },3000)
  9. })
  10. })
  11. hook.tapPromise('1',(name,age)=>{
  12. return new Promise((reslove,reject)=>{
  13. setTimeout(()=>{
  14. console.log(name+1)
  15. reslove('c1')
  16. },1000)
  17. })
  18. })
  19. hook.tapPromise('2',(name,age)=>{
  20. return new Promise((reslove,reject)=>{
  21. setTimeout(()=>{
  22. console.log(name+2)
  23. reslove('c2')
  24. },2000)
  25. })
  26. })
  27. hook.promise('GMX','18').then((res)=>{
  28. console.log('res:'+res);
  29. })
  30. //"GMX3"
  31. //"GMX1"
  32. //"GMX2"
  33. //"res:undefined"

AsyncSeriesHook

异步串行执行,一个结束即结束

  1. var tapable = require("tapable")
  2. const hook = new tapable.AsyncSeriesHook(["name", "age"]);
  3. hook.tapPromise('1',(name,age)=>{
  4. return new Promise((reslove,reject)=>{
  5. setTimeout(()=>{
  6. console.log(name+1)
  7. reject('c1')
  8. },1000)
  9. })
  10. })
  11. hook.tapPromise('3',(name,age)=>{
  12. return new Promise((reslove,reject)=>{
  13. setTimeout(()=>{
  14. console.log(name+3)
  15. reslove('c3')
  16. },3000)
  17. })
  18. })
  19. hook.tapPromise('2',(name,age)=>{
  20. return new Promise((reslove,reject)=>{
  21. setTimeout(()=>{
  22. console.log(name+2)
  23. reslove('c2')
  24. },2000)
  25. })
  26. })
  27. hook.promise('GMX','18').then((res)=>{
  28. console.log('res:'+res);
  29. }).catch(e=>{
  30. console.log('err'+e)
  31. })
  32. //"GMX1"
  33. //"errc1"

拦截器 interception

所有的hook 都可以添加拦截器 interception

  1. var {SyncHook} = require("tapable")
  2. const hook = new SyncHook(["name", "age"]);
  3. hook.intercept({
  4. call: (source, target, routesList) => {
  5. console.log("Starting to calculate routes");
  6. },
  7. register: (tapInfo) => {
  8. // tapInfo = { type: "promise", name: "GoogleMapsPlugin", fn: ... }
  9. console.log(`${tapInfo.name} is doing its job`);
  10. return tapInfo; // may return a new tapInfo object
  11. }
  12. })

HookMap

可以通过 hookMap 创建一组hook

  1. const keyedHook = new HookMap(key => new SyncHook(["arg"]))
  2. keyedHook.for("some-key").tap("MyPlugin", (arg) => { /* ... */ });
  3. keyedHook.for("some-key").tapAsync("MyPlugin", (arg, callback) => { /* ... */ });
  4. keyedHook.for("some-key").tapPromise("MyPlugin", (arg) => { /* ... */ });

MultiHook

可以将多个hook 收集起来。

  1. const { MultiHook } = require("tapable");
  2. this.hooks.allHooks = new MultiHook([this.hooks.hookA, this.hooks.hookB]);