webpack plugin
webpack plugin
webpack完成的复杂炫酷的功能依赖于插件机制,webpack的插件机制依赖于核心的库, tapable
tapable是一个类似于nodejs的eventEmitter的库, 主要是控制钩子函数的发布喝定于,当时,tapable提供您的hook机制比较全面,分为同步和异步两个大类, 根据事件执行的终止条件的不同
const {SyncHook}= require('tapable')
const hook = new SyncHook(['arg1', 'arg2'])
hook.tap('a', function(arg1, arg2) {console.log('ar')
})
hook.tap('b',function(arg1, arg2) {console.log('b')
})
hook.call(1, 2)
BasicHook: 执行每一个,不关心函数的返回值,有SyncHook, AsyncParallelHook, AsyncSeriesHook
BailHook: 顺序执行hook,遇到第一个结果result!=undefined则返回,不在执行
SyncBailHook, AsyncSeriesBailHook, AsyncParallelBailHook
tapable => sync => SyncHook=> SyncBailHook=> SyncWaterfallHook=> SyncLoopHook=> Async => AsyncParallel => AsyncParallelHook => AsyncParallelBailHook=> AsyncSeries => AsyncSeriesHook=> AsyncParallelBailHook=> AsyncSeriesLoopHook=> AsyncSeriesWaterfallHook
每个Hook的用法
Basic: 不关心回调函数返回值,[SyncHook, AsyncParallelHook, AsyncSeriesHook]
Bail: 只要其中一个监听函数的返回值,不为undefined,则终止执行。 [SyncBailHook, AsyncParallelHook, AsyncSeriesBailHook]
waterfall: 前一个监听函数的返回值部位undefined,则作为下一个监听函数的第一个参数
[SyncWaterfallHook, AsyncSeriesWaterfallHook]
Loop: 如果有一个监听函数的返回值不为undefined, 则终止向下执行,从头开始执行,直到所有监听函数的返回值为undefined。[SyncLoopHook, AsyncSeriesLoopHook]~
```javascript
const {SyncHook} = require('tapable')
let hook = new SyncHook(['name'])
hook.tap('demo', function(params) {console.log('demo', params)
})
hook.tap('demo2', function(params) {console.log('demo2', params)return true
})
hook.tap('demo3', function(params) {console.log('demo3', params)
})
hook.call('hello SyncHook')
class SyncHook {constructor(args = []) {this._args = argsthis.tasks = []}tap(name, task) {this.tasks.push(task)}call(...args) {const params = args.slice(0, this._args.length)this.tasks.forEash(task => task(...params))}
}
const {SyncBailHook} = require('tapable')
let hook = new SyncBailHook(['name'])
hook.tap('demo', function(params) {console.log('demo', params)
})
hook.tap('demo2', function(params) {console.log('demo2', params)return true
})
hook.tap('demo3', function(params) {console.log('demo3', params)
})
hook.call('hello SyncBailHook')
SyncBailHook钩子遇到回调函数中返回结果不为undefined的时候,则跳过下面所有的逻辑
class SyncBailHook {constructor(args) {this._args = _argsthis.tasks = []}tap(name, task) {this.tasks.push(task)}call() {const args = Array.from(arguments).slice(0, this._args.length)for(let i = 0; i < this.tasks.length; i++) {if(result !== undefiend) {break}}}
}
SyncWaterfallHook
const {SyncWaterfallHook} = require('tapable')
const hook = new SyncWaterfallHook(['author', 'age'])
hook.tap('测试1', (params1, params2) => {console.log('测试1接受的参数', params1, params2)
})
hook.tap('测试2', (params1, params2) => {console.log('测试2接受的参数', params1, params2)
})
hook.tap('测试3',(params1, params2) => {console.log('测试3接受的参数', params1, params2)
})
hook.call('嘎嘎嘎', '99')
syncWaterfallHook是一个同步的,瀑布类型的hook,瀑布类型的钩子就是如果前一个事件的函数结果部位undefined,则result会作为后一个事件函数的第一个参数,也就是上一个函数的执行结果会成为下一个函数的参数
const {SyncLoopHook} = require('tapable')
const hook = new SyncLoopHook([])
let count = 5
hook.tap('测试1', () => {console.log("测试1里面的count", count)if([1, 2, 3].includes(count) {return undefiend} else {count--return "123"})
})
hook.tap('测试2', () => {console.log("测试2里面的count", count)if([1, 2].includes(count) {return undefiend} else {count--return "123"})
})
hook.tap("测试3", () => {console.log("测试3里面的count",count)if([1].includes(count) {return undefiend} else {count--return "123"})
})
hook.call()
syncLoophook=>asyncparallelHook是一个异步并行,基本类型的Hook, 与同步不同的地方在于
- 会同时开启多个异步任务,而且需要通过tapSaync
const {AsyncParallelHook} = require("tapable")
const hook = new AsyncParallelHook(['author', 'age'])
console.log('time')
hook.tapAsync('测试1', (params1, params2) {setTimeout(() => {console.log('测试1接受的参数', params1, params2)callback()}, 2000)
})
hook.tapAsync('测试2', (params1, params2, callback) {console.log("测试2接受的参数", params1, params2)callback()
})
hook.tapAsync('测试3',(params1, params2,callback) => {console.log("测试3接受的参数", params1, params2)callback()
})
hook.callAsync('嘎嘎嘎', "99",(err, result) => {console.log("这个是成功的回调",err, result)console.timeEnd("time")
})
AsyncParallelBailHook是一个异步并行,保险类型的hook,只要其中一个有返回值, 就会执行callAsync中的回调
const {AsyncParallelHook} = require('tapable')
const hook = new AsyncParallelBailHook(['author', 'age'])
console.time('time')
hook.tapAsync('测试1', (params1, params2, callback) => {console.log('测试1接受的参数',params1, params2)setTimeout(() => {callback()},1000)
})
hook.tapAsync("测试2", (params1,params2,callback) => {console.log('测试2接受的参数',params1, params2) setTimeout(() => {callback(null, '测试2有返回值')}, 2000)
})
hook.tapAsync('测试3', (params1, params2, callback) => {console.log('测试3接受的参数',params1, params2)setTimeout(()=> {callback(null, '测试3有返回值')}, 3000)
})
hook.callAsync("嘎嘎嘎", "99", (err, result) => {//等全部都完成了才会走到这里来console.log("这是成功后的回调", result);console.timeEnd("time");
});
AsyncSeriesHook是一个异步的,串行的类型的hook,只有前面的执行完成了,后面的才会执行
const {AsyncSeriesHook} = require('tapable')
const hook = new AsyncSeriesHook(['author', 'age'])
console.time('time')
hook.tapAsync('测试1', (params1, params2, callback) => {console.log('测试1接受的参数', params1, params2)setTimeout(() => {callback()}, 1000)
})
hook.tapAsync('测试2', (params1, params2, callback) => {console.log('测试2接受的参数', params1, params2)setTimeout(() => {callback()}, 2000)
})
hook.tapAsync('测试3', (params1, params2, callback) => {console.log('测试3接受的参数', params1, params2)setTimeout(() => {callback()}, 3000)
})
console.timeEnd()
AsyncSeriesBailHook 是一个异步串行,保险类型的hook,在串行的执行过程中,只要其中一个有返回值,后面就不会执行
const {AsyncSeriesBailHook} = require('tapable')
const hook = new AsyncParallelHook(['author', 'age'])
hook.tapAsync('测试1',(params1, params2, callback) => {console.log('测试1接受的参数',params1, params2)setTimeout(() => {callback()}, 1000)
})
hook.tapAsync('测试2',(params1, params2,callback) {console.log('测试2接受的参数',params1, params2)setTimeout(() => {callback()}, 2000)
})
hook.tapAsync('测试3',(params1, params2,callback) {console.log('测试3接受的参数',params1, params2)setTimeout(() => {callback()}, 3000)
})
hook.callAsync("嘎嘎嘎", "99", (err, result) => {//等全部都完成了才会走到这里来console.log("这是成功后的回调", result);console.timeEnd("time");
});
AsyncSeriesWaterfallHook是一个异步串行,瀑布类型的hook, 如果前一个事件函数的结果result!==undefined,则result会作为后一个事件函数的第一个参数,也就是上一个函数的执行结果会称为下一个函数的参数
const {AsyncSeriesWaterfallHook} = require('tapable')
const hook = new AsyncSeriesWaterfallHook(['author', 'age'])
console.time('time')
hook.tapAsync("测试1", (params1, params2, callback) => {console.log('测试1接受的参数', params1, params2)setTimeout(() => {callback(() => {callback(null, '2')}, 1000)})
})
hook.tapAsync("测试2", (params1, params2, callback) => {console.log('测试2接受的参数', params1, params2)setTimeout(() => {callback(null, '3')},2000)
})
hook.tapAsync("测试3", (param1, param2, callback) => {console.log("测试3接收的参数:", param1, param2);setTimeout(() => {callback(null, "4");}, 3000);
});hook.callAsync("嘎嘎嘎", "99", (err, result) => {//等全部都完成了才会走到这里来console.log("这是成功后的回调", err, result);console.timeEnd("time");
});
Tapable拦截器
Tapable提供的所有的hook都支持注入Interception,它和Axios的拦截器的效果非常类似,可以通过拦截器对整个Tapable发布/订阅流程进行监听,从而触发对应的逻辑
const hook = new SyncHook(['arg1', 'arg2', 'arg3'])
hook.intercept({// 每次调用hook实例的tap,方法注册回调函数的时候,就会调用该方法// 并且接受tap作为参数,还可以对tap进行修改register: (tapInfo) => {console.log(`${tapInfo.name} is doing its job`)return tapInfo},// 通过hook实例对象上的call方法时候触发拦截器call: (arg1, arg2, arg3) => {console.log('starting to calculate routes')}// 在调用被注册的每一个事件函数之前执行tap: (tap) => {console.log(tap, 'tap'))}// loop类型钩子中,每个事件函数被调用前触发拦截器方法 loop:(...args) => {console.log(args, 'loop')}
})
相关文章:
webpack plugin
webpack plugin webpack完成的复杂炫酷的功能依赖于插件机制,webpack的插件机制依赖于核心的库, tapable tapable是一个类似于nodejs的eventEmitter的库, 主要是控制钩子函数的发布喝定于,当时,tapable提供您的hook机…...
【busybox记录】【shell指令】date
目录 内容来源: 【GUN】【date】指令介绍 【busybox】【date】指令介绍 【linux】【date】指令介绍 使用示例: 打印前天的日期: 打印三个月零一天后的日期: 打印当年圣诞节的年数: 打印当前的全月名称和月的日期: 要打印一个没有前导零的日期&…...
同态加密和SEAL库的介绍(八)性能
本篇会对比三种加密方案,同时每种方案配置三种参数。即九种情况下的各个操作的性能差异,为大家选择合适的方案和合适的参数提供参考。表格中所有时长的单位均为微妙,即 。 当然数据量比较大,为了方便大家查找,…...
华为OD-D卷数的分解
给定一个正整数n,如果能够分解为m(m > 1)个连续正整数之和,请输出所有分解中,m最小的分解。 如果给定整数无法分解为连续正整数,则输出字符串"N"。 输入描述: 输入数据为一整数,范围为(1, 2^3…...
rk3588 low_delay_net_display注意事项
low_delay_net_display例子默认只支持YUV420和RGB888,如果需要支持YUV422,请添加下面部分: rk3588_nvr/build/app/low_delay_net_display$ git diff v4l2HdmiRX.cpp diff --git a/app/low_delay_net_display/v4l2HdmiRX.cpp b/app/low_delay_net_displa…...
Spring Boot 快速入门样例【后端 3】
Spring Boot 入门:从零到一构建你的第一个应用 Spring Boot 作为一个流行的Java框架,以其“习惯优于配置”的理念极大地简化了Spring应用的开发和部署过程。本文将带你一步步创建一个简单的Spring Boot应用,从环境准备到项目创建,…...
Linux云计算 |【第二阶段】NETWORK-DAY2
主要内容: VLAN技术、TRUNK模式、链路聚合、路由器 一、VLAN技术应用 广播域指接受同样广播消息的节点的集合,如在该集合中的任何一个节点传输一个广播帧,则所有其它能收到这个帧的节点都被认为是该广播帧的一部分; 交换机的所有…...
Java面试题(基础篇)③
目录 一, 与 equals 的区别? 二,接口和抽象类的区别? 三,请说出几个常见的异常? 四,请问你对Java 反射有了解吗? 五,浅拷贝和深拷贝区别? 一,…...
Qt动态调用 - QMetaObject::invokeMethod
QMetaObject::invokeMethod 动态调用是 Qt 的元对象系统的一项强大功能,它允许在运行时通过名称调用槽函数、信号和普通成员函数。 这种能力对于构建灵活和可扩展的应用程序非常有用,比如插件系统或脚本接口。 动态调用方法 Qt 提供了 QMetaObject::i…...
html+css+js网页设计 星享咖啡6个页面(带js) ui还原度90%
htmlcssjs网页设计 星享咖啡6个页面(带js) ui还原度90% 网页作品代码简单,可使用任意HTML编辑软件(如:Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等…...
docker上传镜像至阿里云
1、安装wsl2 WSL2安装(详细过程) 2、安装docker Docker在Windows下的安装及使用 3、创建私人阿里云镜像库 如何创建私人阿里云镜像仓库?(保姆级) 4、如何删除容器 (1) 查找正在使用该图像的容器 docker ps -a --filte…...
POS刷卡开发源码之语音播报-CyberWinApp-SAAS 本地化及未来之窗行业应用跨平台架构
一、终端语音提醒的好处 1. 增强信息传递的有效性:在人们忙碌或者注意力分散时,语音提醒能够直接穿透噪音和干扰,确保重要信息被准确接收。 2. 提高操作的便捷性:用户无需停下手中的工作去查看屏幕或阅读文字,直接通过…...
jupyter notebook魔法命令
%xmode 魔法命令来控制异常报告: 输入魔法命令:在 IPython 或 Jupyter Notebook 的一个新单元格中,输入以下命令之一来设置异常报告模式: 切换到 Plain 模式(简洁输出): %xmode Plain切换回 Con…...
Mysql事件
1:查询全局事件开关是否启动 SHOW VARIABLES LIKE %sche%; 关闭状态!!!去开启如果已开启忽略 set global event_scheduler ON; ojbk 2:创建事件 step1: 链接打开自己的数据库 step2: 找…...
Unity Console 窗口输出对齐
起因:做了个工具在console窗口罗列一些信息,基本结构是 [ 文件名 :行号 ],因为文件,行号长度不一,想要做到如下效果。 初步尝试,用以下方法: string format "{0,-10} …...
leetcode198_打家劫舍
思路 动态规划 func rob(nums []int) int {if len(nums) < 2 {return nums[0]}// dp[i] 表示到第i家为止,小偷能够偷窃到的最高金额dp : make([]int, len(nums))dp[0] nums[0]dp[1] max(nums[0], nums[1])for i:2; i<len(nums); i {if nums[i] dp[i-2] &…...
C# 串口通讯怎么防止数据丢失
串口通信(Serial Communication)是计算机与设备之间进行数据交换的一种方式。在C#中进行串口通信时,防止数据丢失可以采取以下一些措施: 1.校验和(Checksum):在发送数据时,计算数据的…...
【机器学习】BP神经网络中的链式法则:解开智能背后的数学奥秘
在浩瀚的机器学习领域中,BP(反向传播)神经网络如同一座桥梁,连接着复杂的数据世界与智能的彼岸。而这座桥梁的基石之一,便是链式法则(Chain Rule)——一个看似简单却蕴含无限智慧的数学原理。今…...
MyBatis 基本操作 - 注解版
目录 一,查询 - select 1.1 全列查询 1.2 指定列查询 1.3 赋值问题 方法一:起别名 方法二:结果映射 方法三:添加配置 二,新增 - Insert 2.1 使用对象插入 2.2 获取主键 三,删除 - Delete 四&am…...
专业比例阀放大器配套选型
比例阀放大器作为液压系统中的关键组件,其技术选型对于保障系统的精确控制、稳定性和长期可靠性至关重要。下面将深入探讨比例阀放大器的技术选型要点,确保选型能满足特定的应用需求和系统性能要求: 兼容性与安装方式 阀型匹配:…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
