浅谈 Tapable

64 阅读1分钟

1、Tapable 对外暴露了 9 种 Hooks 类,通过实例化来创建一个执行流程,并提供注册和执行方法

const {
    SyncHook,
    SyncBailHook,
    SyncWaterfallHook,
    SyncLoopHook,
    AsyncParallelHook,
    AsyncParallelBailHook,
    AsyncSeriesHook,
    AsyncSeriesBailHook,
    AsyncSeriesWaterfallHook
 } = require("tapable");

2、按同步、异步(串行、并行)分类

image.png

3、按执行模式分类

  • Basic:执行每一个事件函数,不关心函数的返回值
  • Bail:执行每一个事件函数,遇到第一个结果 result !== undefined 则返回,不再继续执行
  • Waterfall:如果前一个事件函数的结果 result !== undefined,则 result 会作为后一个事件函数的第一个参数
  • Loop:不停的循环执行事件函数,直到所有函数结果 result === undefined

image.png

4、使用案例

简单来说就是下面步骤

  1. 实例化构造函数 Hook
  2. 注册(一次或者多次)
    • tap: 注册同步监听器。
    • tapAsync: 注册异步监听器,使用回调函数。
    • tapPromise: 注册异步监听器,使用 Promise。
  3. 执行(传入参数)
    • call: 触发同步钩子。
    • callAsync: 触发异步钩子,使用回调函数。
    • promise: 触发异步钩子,返回 Promise。
  4. 如果有需要还可以增加对整个流程(包括注册和执行)的监听-拦截器

案例

const { SyncHook, AsyncParallelHook, WaterfallHook, AsyncSeriesHook } = require('tapable');

// SyncHook 示例
const syncHook = new SyncHook(['name']);
syncHook.tap('Listener1', (name) => {
  console.log(`Hello ${name} from Listener1`);
});
syncHook.tap('Listener2', (name) => {
  console.log(`Hello ${name} from Listener2`);
});
syncHook.call('Alice');


// AsyncParallelHook 示例
const asyncParallelHook = new AsyncParallelHook(['name']);
asyncParallelHook.tap('Listener1', (name, callback) => {
  setTimeout(() => {
    console.log(`Hello ${name} from Listener1`);
    callback();
  }, 1000);
});
asyncParallelHook.tapPromise('Listener2', async (name) => {
  await new Promise((resolve) => setTimeout(resolve, 500));
  console.log(`Hello ${name} from Listener2`);
});
asyncParallelHook.call('Bob', () => {
  console.log('All listeners finished');
});
asyncParallelHook.promise('Bob').then(() => {
  console.log('All listeners finished');
});


// WaterfallHook 示例
const waterfallHook = new WaterfallHook(['name']);
waterfallHook.tap('Listener1', (name) => {
  console.log(`Hello ${name} from Listener1`);
  return `${name} updated`;
});
waterfallHook.tap('Listener2', (name) => {
  console.log(`Hello ${name} from Listener2`);
  return `${name} final`;
});
const result = waterfallHook.call('Carol');
console.log(result);


// AsyncSeriesHook 示例
const asyncSeriesHook = new AsyncSeriesHook(['name']);
asyncSeriesHook.tap('Listener1', (name, callback) => {
  setTimeout(() => {
    console.log(`Hello ${name} from Listener1`);
    callback();
  }, 1000);
});
asyncSeriesHook.tapPromise('Listener2', async (name) => {
  await new Promise((resolve) => setTimeout(resolve, 500));
  console.log(`Hello ${name} from Listener2`);
});
asyncSeriesHook.call('Dave', () => {
  console.log('All listeners finished');
});
asyncSeriesHook.promise('Dave').then(() => {
  console.log('All listeners finished');
});