tapable工作流程
- 实例化hook注册事件监听
- 通过hook触发事件监听
- 执行懒编译生成的可执行代码
Hook本职是tapable实例对象,分同步和异步,异步分并行和串行两种模式
Hook执行特点
Hook:一般钩子,监听器之间相互独立不烦扰
BailHook:熔断钩子,某个监听返回非undefined时后续不执行
WaterfallHoook: 瀑布钩子,上一个监听的返回值可传递至下一个
LoopHook:循环钩子,如果以后未返回false则始终执行
tapable库同步钩子:SynckHook,SyncBailHoook,SyncWaterfallHook,SyncLoopHook
异步串行钩子:AsyncSeriesHoook,AsyncSeriesBailHook,AsyncSeriesWaterfallHook,异步并行钩子:AsyncParallerHook,AsyncParalleBailHook
同步钩子:
SyncHook
let { SyncHook, SyncBailHook} = require('tapable')// 创立钩子let hook = new SyncHook(['name', 'age'])hook.tap('fn1', function (name, age) { console.log('fn1', name, age)})hook.tap('fn2', function (name, age) { console.log('fn2', name, age)})hook.tap('fn3', function (name, age) { console.log('fn3', name, age)})hook.call('jack', 18)
后果都能因而打印
SyncBailHook
let bailHook = new SyncBailHook(['name', 'age'])bailHook.tap('fn1', function (name, age) { console.log('fn1', name, age)})bailHook.tap('fn2', function (name, age) { console.log('fn2', name, age) return 'tom' // fn1,fn2,会打印,fn3不会打印 // return undefined // fn1,fn2,fn3都会打印})bailHook.tap('fn3', function (name, age) { console.log('fn3', name, age)})bailHook.call('jack', 18)
如果返回非undefined
,流程就会终止
SyncWaterfallHook
let waterfallhook = new SyncWaterfallHook(['name', 'age'])waterfallhook.tap('fn1', function (name, age) { console.log('fn1', name, age) return 'fn1'})waterfallhook.tap('fn2', function (name, age) { console.log('fn2', name, age) return 'fn2'})waterfallhook.tap('fn3', function (name, age) { console.log('fn3', name, age) return 'fn3'})waterfallhook.call('jack', 18)
SyncWaterfallHook
能够通过return把返回值传递给下一个钩子
SyncLoopHook
let loophook = new SyncLoopHook(['name', 'age'])let cnt1 = 0let cnt2 = 0let cnt3 = 0loophook.tap('fn1', function (name, age) { console.log('fn1', name, age) if (++cnt1 === 2) { cnt1 === 0 return undefined } return true})loophook.tap('fn2', function (name, age) { console.log('fn2', name, age)})loophook.tap('fn3', function (name, age) { console.log('fn3', name, age)})loophook.call('jack', 18)
tap函数体内设置了判断条件,如果不满足条件,SyncLoopHook
会重头开始继续执行
异步钩子
对于异步钩子的应用,在增加事件监听时会存在三种形式:tap
、 tapAsync
、 tapPromise
异步并行钩子:AsyncParallerHook
tap
形式监听
let hook = new AsyncParallelHook(['name'])hook.tap('fn1', function (name) { console.log('fn1', name)})hook.tap('fn2', function (name) { console.log('fn2', name)})hook.callAsync('jack', function () { console.log('operate async')})
tapAsync
形式监听
console.time('time')hook.tapAsync('fn1', function (name, callback) { setTimeout(() => { console.log('fn1', name) callback() }, 1000);})hook.tapAsync('fn2', function (name, callback) { setTimeout(() => { console.log('fn2', name) callback() }, 2000);})hook.callAsync('jack', function () { console.log('operate tapAsync') console.timeEnd('time')})
从执行后果来看,是并行执行
tapPromise
形式监听
console.time('time')hook.tapPromise('fn1', function (name) { return new Promise(function (resolve, reject) { setTimeout(() => { console.log('fn1', name) resolve() }, 1000); })})hook.tapPromise('fn2', function (name) { return new Promise(function (resolve, reject) { setTimeout(() => { console.log('fn2', name) resolve() }, 2000); })})hook.promise('jack').then(() => { console.log('end') console.timeEnd('time')})
AsyncParallelBailHook
let hook = new AsyncParallelBailHook(['name']);console.time('time')hook.tapAsync('fn1', function (name, callback) { setTimeout(() => { console.log('fn1', name) callback() }, 1000);})hook.tapAsync('fn2', function (name, callback) { setTimeout(() => { console.log('fn2', name) callback('err') // 熔断操作 }, 2000);})hook.tapAsync('fn3', function (name, callback) { setTimeout(() => { console.log('fn3', name) callback() }, 3000);})hook.callAsync('jack', function () { console.log('end') console.timeEnd('time')})
fn3
最初是执行了,然而在fn2
后就熔断了.
AsyncSeriesHook
串行
let hook = new AsyncSeriesHook(['name'])console.time('time')hook.tapPromise('fn1', function (name) { return new Promise((resolve, reject) => { setTimeout(() => { console.log('fn1', name) resolve() }, 1000); })})hook.tapPromise('fn2', function (name) { return new Promise((resolve, reject) => { setTimeout(() => { console.log('fn2', name) resolve() }, 2000); })})hook.promise('fn').then(function () { console.log('end') console.timeEnd('time')})
从后果来看,代码是串行执行