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会重头开始继续执行

异步钩子

对于异步钩子的应用,在增加事件监听时会存在三种形式:taptapAsynctapPromise
异步并行钩子: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')})


从后果来看,代码是串行执行