webpack的灵魂tapable学习笔记

tapable 本质上是一种事件流的机制,帮助咱们将各个插件串联起来 包含(发布订阅模式)promise

1.SyncHook用法

let { SyncHook } = require('tapable')
class Animals {
    constructor() {
        this.hooks = {
            mam: new SyncHook(['name'])
        }
    }
    tap() {
        this.hooks.mam.tap('cat', function (name) {
            console.log('cat', name)
        })
        this.hooks.mam.tap('dog', function (name) {
            console.log('dog', name)
        })
    }
    start() {
        this.hooks.mam.call('mam')
    }
}
let animals = new Animals()
animals.tap() // 订阅方法
animals.start() // 发布
复制代码

本身实现SyncHook

class SyncHook {
    constructor(args) {
        this.tasks = []
    }
    tap(name, task) {
        this.tasks.push(task)
    }
    call(...args) {
       this.tasks.forEach((task) => {
           task(...args)
       })
    }
}
let hook = new SyncHook(['name'])
hook.tap('cat',function(name){
    console.log('cat', name)
})
hook.tap('dog',function(name){
    console.log('dog', name)
})
hook.call('mam')

// dog mam
// cat mam

复制代码

2.SyncBailHook

串行同步执行,有一个返回值不为undefined就跳过剩下逻辑, bail是保险的意思,表示有一个出错就不往下执行了bash

let { SyncBailHook } = require('tapable')
class Animals {
    constructor() {
        this.hooks = {
            mam: new SyncBailHook(['name'])
        }
    }
    tap() {
        this.hooks.mam.tap('cat', function (name) {
            console.log('cat', name)
            return '喵喵叫' // 返回了一个非 undefined值 不继续执行
        })
        this.hooks.mam.tap('dog', function (name) {
            console.log('dog', name)
        })
    }
    start() {
        this.hooks.mam.call('mam')
    }
}
let animals = new Animals()
animals.tap()
animals.start()

// cat mam
复制代码

本身实现SyncBailHook

class SyncBailHook {
    constructor(args) {
        this.tasks = []
    }
    tap(name, task) {
        this.tasks.push(task)
    } 
    call(...args) { // 循环全部订阅tasks,若是有一个函数的返回值不为undefined跳出循环,以后的函数都不执行
        let ret
        let index = 0
      do{
        ret = this.tasks[index++](...args)
      }while(ret === undefined && index<this.tasks.length)
    }
}
let hook = new SyncBailHook(['name'])
hook.tap('cat',function(name){
    console.log('cat', name)
    return 'miao'
})
hook.tap('dog',function(name){
    console.log('dog', name)
})
hook.call('mam')
复制代码

3.SyncWaterfallHook

就想水流动同样,下一个任务能够获得上一个任务的返回值异步

let { SyncWaterfallHook } = require('tapable')
class Animals {
    constructor() {
        this.hooks = {
            mam: new SyncWaterfallHook(['name'])
        }
    }
    tap() {
        this.hooks.mam.tap('cat', function (name) {
            console.log('cat', name)
            return 'eat food'
        })
        this.hooks.mam.tap('dog', function (name) {
            console.log('dog', name)
        })
    }
    start() {
        this.hooks.mam.call('mam')
    }
}
let animals = new Animals()
animals.tap()
animals.start()

// cat mam
// dog eat food
复制代码

本身实现SyncWaterfallHook

class SyncWaterfallHook {
    constructor(args) {
        this.tasks = []
    }
    tap(name, task) {
        this.tasks.push(task)
    }
    call(...args) {
      let [first,...others] = this.tasks
      let ret = first()       // 结构出当前第一个函数执行
      others.reduce((pre, next) => {
        return next(pre) 
      }, ret) 
      
      // ret传入reduce,至关于第一次循环pre等于ret,执行下一个函数后返回值等于第二次循环pre。这样每次循环pre都有返回值
      
    }
}
let hook = new SyncWaterfallHook(['name'])
hook.tap('cat',function(name){
    console.log('cat', name)
    return 'eat food'
})
hook.tap('dog',function(name){
    console.log('dog', name)
})
hook.call('mam')

// cat undefined
// dog eat food
复制代码
  • tapabel中有三种注册方式

tap: 同步注册 tapAsync: 异步注册 tapPromise: 注册时promise函数

  • 分别对应三种调用方式

call callAsync promiseui

相关文章
相关标签/搜索