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

相關文章
相關標籤/搜索