Tapable

Tapable 的使用

Tapable 本身不能使用,只能使用從它導(dǎo)出的 Hook

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

Hook 可以按照兩種標(biāo)準(zhǔn)來分類

  1. 事件回調(diào)的運(yùn)行邏輯:
  • Basic:基本類型,按順序執(zhí)行注冊(cè)的回調(diào)
  • Bail:保險(xiǎn)類型,當(dāng)一個(gè)事件回調(diào)的返回值不為 undefined 時(shí),停止后面的回調(diào)執(zhí)行
  • Waterfall:瀑布類型,如果當(dāng)前事件回調(diào)的返回值不為 undefined,那么返回值就作為下一個(gè)回調(diào)的第一個(gè)參數(shù)
  • Loop:循環(huán)類型,如果當(dāng)前事件回調(diào)的返回值不為 undefined,回到第一個(gè)事件注冊(cè)的回調(diào)執(zhí)行,直到所有的回調(diào)都返回 undefined(沒有返回)
  1. 觸發(fā)事件的方式:
  • Sync:以 sync 開頭的 hook,同步的執(zhí)行注冊(cè)的事件;只能使用 tap 方法注冊(cè),使用 tapAsync 或 tapPromise 注冊(cè)會(huì)報(bào)錯(cuò)
  • AsyncSerise:以 asyncSerise 開頭的 hook,按順序的執(zhí)行事件回調(diào),如果回調(diào)是異步的,等異步執(zhí)行完成才會(huì)執(zhí)行下一個(gè)事件回調(diào);可以使用 tap、tapAsync、tapPromise 注冊(cè)事件回調(diào);不能使用 call() 方法觸發(fā)回調(diào)
  • AsyncParalle:以 asyncParalle 開頭的 hook,并行的執(zhí)行所有的事件回調(diào)

Sync hook

// 實(shí)例化 Hook
const { SyncHook } = require('tapable');
// 實(shí)例化鉤子類時(shí)傳入的數(shù)組,實(shí)際上只用上了數(shù)組的長(zhǎng)度,名稱是為了便于維護(hù)
const hook = new SyncHook(['name']);

// 事件注冊(cè)
hook.tap('first', (name) => {
  console.log('first ', name);
});
// 第一個(gè)參數(shù)可以是事件回調(diào)的名字,也可以是配置對(duì)象
hook.tap({name: 'second'}, (name) => {
    console.log('second ', name);
});

//觸發(fā)
hook.call('jack'); // 對(duì)應(yīng) sync hook

/**
 * Console output:
 * 
 * first jack
 * second jack
 */

AsyncSerise hook

const { AsyncSeriesHook } = require('tapable');
const hook = new AsyncSeriesHook(['name']);

// 事件回調(diào)接收到 callback
hook.tapAsync('first', (name, callback) => {
  console.log('first', name, callback);
  callback();
});

// 最后一個(gè)傳入?yún)?shù)是回調(diào)函數(shù)
hook.callAsync('callAsync', (error) => {
    console.log('callAsync', error);
});

/**
 * Console output:
 * 
 * first callAsync [Function]
 * callAsync undefined
 */

callAsync 的第二個(gè)參數(shù):錯(cuò)誤回調(diào)callback

  • 事件回調(diào)中必須調(diào)用 callback,才能執(zhí)行下一個(gè)事件回調(diào)
  • 調(diào)用 callback 時(shí)不傳入?yún)?shù)時(shí)執(zhí)行下一個(gè)回調(diào),傳入第一個(gè)參數(shù)代表有錯(cuò)誤發(fā)生,接下來會(huì)執(zhí)行觸發(fā)時(shí)的回調(diào)

Async hook 使用 tapPromise 注冊(cè)

const { AsyncSeriesHook } = require('tapable');
const hook = new AsyncSeriesHook(['name']);

hook.tapPromise('first', (name) => {
  console.log('first', name);

  return Promise.resolve('first');
});

hook.tapPromise('second', (name) => {
  console.log('second', name);

  return Promise.resolve('second');
});

const promise = hook.promise('promise');

console.log(promise);

promise.then(value => {
  // value 是 undefined,不會(huì)接收到事件回調(diào)中傳入的值
  console.log('value', value);
}, reason => {
  // 事件回調(diào)返回的 Promise 對(duì)象狀態(tài)是 Rejected
  // reason 會(huì)有事件回調(diào)中傳入的錯(cuò)誤信息
  console.log('reason', reason);
});

/**
 * Console output:
 * 
 * first promise
 * Promise { <pending> } // 同步代碼
 * second promise  // tapPromise 是微任務(wù),所以會(huì)在同步代碼后執(zhí)行
 * value undefined
 */

promise 執(zhí)行之后會(huì)返回一個(gè) Promise 對(duì)象。在使用 tapPromise 注冊(cè)事件回調(diào)時(shí),事件回調(diào)必須返回一個(gè) Promise 對(duì)象,否則會(huì)報(bào)錯(cuò),這是為了確保事件回調(diào)能夠按照順序執(zhí)行。
攔截器
我們可以給鉤子類添加攔截器,這樣就能對(duì)事件回調(diào)的注冊(cè)、調(diào)用以及事件的觸發(fā)進(jìn)行監(jiān)聽

const { SyncHook } = require('tapable');
const hook = new SyncHook();

hook.intercept({
  // 注冊(cè)時(shí)執(zhí)行
  register(tap) {
    console.log('register', tap);
    return tap;
  },
  // 觸發(fā)事件時(shí)執(zhí)行
  call(...args) {
    console.log('call', args);
  },
  // 在 call 攔截器之后執(zhí)行
  loop(...args) {
    console.log('loop', args);
  },
  // 事件回調(diào)調(diào)用前執(zhí)行
  tap(tap) {
    console.log('tap', tap);
  },
});

參考鏈接:https://zhuanlan.zhihu.com/p/100974318

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容