Tapable(一)

Tapable(一)

  Webpack本质上是一种事件流的机制,它的工作流程就是将各个插件串联起来,而实现这一切的核心就是Tapable。
  Tapable 是一个小型的库,允许你对一个 javascript 模块添加和应用插件。它可以被继承或混入到其他模块中。除此之外,Tapable 还允许你通过回调函数的参数,访问事件的“触发者(emittee)”或“提供者(producer)”。

示意图(引用):
在这里插入图片描述

   打开 Webpack 4.0 的源码中一定会看到下面这些以 Sync、Async 开头,以 Hook 结尾的方法,这些都是 tapable 核心库的类,为我们提供不同的事件流执行机制,我们称为 “钩子”。
  Tapable 提供同步(Sync)和异步(Async)钩子类。而异步又分为异步串行、异步并行钩子类。

const {
    SyncHook,
    SyncBailHook,
    SyncWaterfallHook,
    SyncLoopHook,
    AsyncParallelHook,
    AsyncParallelBailHook,
    AsyncSeriesHook,
    AsyncSeriesBailHook,
    AsyncSeriesWaterfallHook
 } = require("tapable");
安装tapable:
yarn add tapable
同步钩子类

通过实例的 tap 方法监听函数, 通过 call发布事件

一、SyncHook:

同步串行,不关心订阅函数执行后的返回值是什么,在触发事件之后,会按照事件注册的先后顺序执行所有的事件处理函数。其原理是将监听(订阅)的函数存放到一个数组中, 发布时遍历数组中的监听函数并且将发布时的 arguments传递给监听函数

	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']);
	
	//tap传入两个参数:名字 (名字没有什么实际意义)、回调
	hook.tap('react',function(name){
	    console.log('react',name)    // react lzy
	})
	hook.tap('node',function(name){
	    console.log('node',name)   //node  lzy
	})
	hook.call('lzy')

二、SyncBailHook

同步串行,如果事件处理函数执行时返回值为undefined,则继续执行;否则停止向下执行(Bai保险)

	class SyncBailHook {
	    constructor(args) {
	        this.tasks = [];
	    }
	    tap(name, task) {
	        this.tasks.push(task);
	    }
	    call(...args) {
	        let ret;  //ret 当前函数的返回值
	        let index = 0;  // 当前要先执行第一个
	        do{
	            ret = this.tasks[index++](...args)
	        }while(ret === undefined && index<this.tasks.length);   // ===undefined 继续执行
	    }
	}
	
	let hook = new SyncBailHook(['name']);
	hook.tap('vue',function(name){
	    console.log('vue',name)    // vue lzy
	})
	hook.tap('react',function(name){
	    console.log('react',name)   // react lzy
	    return '停止向下执行'
	})
	hook.tap('node',function(name){    // 不执行此处代码
	    console.log('node',name)  
	})
	hook.call('lzy')

三、SyncWaterfallHook

同步串行瀑布流,瀑布流指的是第一个监听函数的返回值,做为第二个监听函数的参数。第二个函数的返回值作为第三个监听函数的参数,依次类推…

	class SyncWaterfallHook {
	    constructor(args) {
	        this.tasks = [];
	    }
	    tap(name, task) {
	        this.tasks.push(task);
	    }
	    call(...args) {
	      let [first,...others] = this.tasks;
	      let ret = first(...args);
	      others.reduce((a,b)=>{
	        return b(a);
	      },ret)
	    }
	}
	
	let hook = new SyncWaterfallHook(['name']);
	hook.tap('vue',function(name){
	    console.log('vue',name)     // vue lzy
	    return 'vue-ok'
	})
	hook.tap('react',function(data){
	    console.log('react',data)    // react vue-ok
	    return 'react-ok'
	})
	hook.tap('node',function(data){
	    console.log('node',data)   // node react-ok
	})
	hook.call('lzy')

四、SyncLoopHook

同步串行,循环执行(如果监听函数的返回值为 true, 则反复执行当前的监听函数,直到返回值为 undefined则继续执行下面的监听函数)

	class SyncLoopHook {
	    constructor(args) {
	        this.tasks = [];
	    }
	    tap(name, task) {
	        this.tasks.push(task);
	    }
	    call(...args) {
	        this.tasks.forEach(task =>{
	            let ret;
	            do{
	                ret = task(...args)
	            }while(ret !==undefined);
	        });
	    }
	}
	
	let hook = new SyncLoopHook(['name']);
	let total = 0;
	hook.tap('vue',function(name){
	    console.log('vue',name)    // vue lzy(3遍)
	    return ++total ==3?undefined:'继续学';
	})
	hook.tap('react',function(name){
	    console.log('react',name)   // react lzy
	})
	hook.tap('node',function(name){
	    console.log('node',name)   //node lzy
	})
	hook.call('lzy')

参考文章:
https://www.jianshu.com/p/273e1c9904d2
https://www.cnblogs.com/qiqingfu/archive/2019/02/16/10387634.html

(ง •_•)ง  (感谢~~)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值