博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
tapable
阅读量:6206 次
发布时间:2019-06-21

本文共 4105 字,大约阅读时间需要 13 分钟。

webpack是一系列插件的集合。webpack执行采用的是事件流机制,tapable则是webpack事件流机制所依赖的核心库。
tapable提供一系列钩子类,以供插件使用。

const {	SyncHook,	SyncBailHook,	SyncWaterfallHook,	SyncLoopHook,	AsyncParallelHook,	AsyncParallelBailHook,	AsyncSeriesHook,	AsyncSeriesBailHook,	AsyncSeriesWaterfallHook } = require("tapable");复制代码
示例:
定义:

class Car {	constructor() {		this.hooks = {			accelerate: new SyncHook(["newSpeed"]),			brake: new SyncHook(),			calculateRoutes: new AsyncParallelHook(["source", "target", "routesList"])		};	} 	/* ... */}复制代码
使用:

const myCar = new Car();// Use the tap method to add a consumentmyCar.hooks.brake.tap("WarningLampPlugin", () => warningLamp.on());复制代码
可以增加参数:

myCar.hooks.accelerate.tap("LoggerPlugin", newSpeed => console.log(`Accelerating to ${newSpeed}`));复制代码
异步执行的钩子:

myCar.hooks.calculateRoutes.tapPromise("GoogleMapsPlugin", (source, target, routesList) => {	// return a promise	return google.maps.findRoute(source, target).then(route => {		routesList.add(route);	});});myCar.hooks.calculateRoutes.tapAsync("BingMapsPlugin", (source, target, routesList, callback) => {	bing.findRoute(source, target, (err, route) => {		if(err) return callback(err);		routesList.add(route);		// call the callback		callback();	});});// You can still use sync pluginsmyCar.hooks.calculateRoutes.tap("CachedRoutesPlugin", (source, target, routesList) => {	const cachedRoute = cache.get(source, target);	if(cachedRoute)		routesList.add(cachedRoute);})复制代码
调用:

class Car {	/* ... */	setSpeed(newSpeed) {		this.hooks.accelerate.call(newSpeed);	}	useNavigationSystemPromise(source, target) {		const routesList = new List();		return this.hooks.calculateRoutes.promise(source, target, routesList).then(() => {			return routesList.getRoutes();		});	}	useNavigationSystemAsync(source, target, callback) {		const routesList = new List();		this.hooks.calculateRoutes.callAsync(source, target, routesList, err => {			if(err) return callback(err);			callback(null, routesList.getRoutes());		});	}}复制代码
钩子类型:
每个钩子可以添加一个或多个方法,它们的执行分为以下几种方式:
  • 基础类型(名字不带“Waterfall”, “Bail” 或“Loop”)。调用时直接执行每个方法。
  • Waterfall。执行每个方法,但会传递返回值到下一个方法。
  • Bail。当返回值不为undefined时提前结束。
同样还可以分成异步钩子和同步钩子。
  • Sync。同步钩子,只能用同步方法添加函数。(using myHook.tap())
  • AsyncSeries。同步、回调和promise方式添加都可以(using myHook.tap(), myHook.tapAsync() and myHook.tapPromise())。它们会依次执行。
  • AsyncParallel。同样可以同步、回调和promise方式添加(using myHook.tap(), myHook.tapAsync() and myHook.tapPromise())。但是它们会并发执行。
可以根据类名判断钩子类型。比如AsyncSeriesWaterfallHook代表异步按顺序执行并把返回值传递给下一个方法。
拦截器:
所以钩子都提供拦截器api:

myCar.hooks.calculateRoutes.intercept({	call: (source, target, routesList) => {		console.log("Starting to calculate routes");	},	register: (tapInfo) => {		// tapInfo = { type: "promise", name: "GoogleMapsPlugin", fn: ... }		console.log(`${tapInfo.name} is doing its job`);		return tapInfo; // may return a new tapInfo object	}})复制代码
call: (...args) => void call方法调用时触发,你有获取调用参数的权限。
tap: (tap: Tap) => void tap方法触发,提供不可改变的Tap对象。
register: (tap: Tap) => Tap | undefined 注册Tap时触发,Tap对象可修改。
上下文对象(context):
插件和拦截器可以访问一个可选的上下文对象。用于向随后的插件和拦截器传递独有的值。

myCar.hooks.accelerate.intercept({	context: true,	tap: (context, tapInfo) => {		// tapInfo = { type: "sync", name: "NoisePlugin", fn: ... }		console.log(`${tapInfo.name} is doing it's job`);		// `context` starts as an empty object if at least one plugin uses `context: true`.		// If no plugins use `context: true`, then `context` is undefined.		if (context) {			// Arbitrary properties can be added to `context`, which plugins can then access.			context.hasMuffler = true;		}	}});myCar.hooks.accelerate.tap({	name: "NoisePlugin",	context: true}, (context, newSpeed) => {	if (context && context.hasMuffler) {		console.log("Silence...");	} else {		console.log("Vroom!");	}});复制代码
HookMap:
一个钩子map的辅助类

const keyedHook = new HookMap(key => new SyncHook(["arg"]))keyedHook.tap("some-key", "MyPlugin", (arg) => { /* ... */ });keyedHook.tapAsync("some-key", "MyPlugin", (arg, callback) => { /* ... */ });keyedHook.tapPromise("some-key", "MyPlugin", (arg) => { /* ... */ });const hook = keyedHook.get("some-key");if(hook !== undefined) {	hook.callAsync("arg", err => { /* ... */ });}复制代码

参考资料:

转载地址:http://qokja.baihongyu.com/

你可能感兴趣的文章
暴走漫画基于阿里云的全面容器化架构实践
查看>>
PowerDesigner模型设计
查看>>
Android开发获取GPS位置,包含apn\wifi\gps 几种方法
查看>>
TcpDump 抓包 传输数据包
查看>>
利用Rsync服务让SLB下多台centos服务器文件同步更新
查看>>
阳振坤深度解析OceanBase如何支撑支付宝双十一14万/秒笔交易
查看>>
docker 搭建私有仓库及镜像存储目录结构
查看>>
Javascript 函数和变量提升
查看>>
RocketMQ 实战(一) - 简介
查看>>
蚂蚁金服!前端实习生!内推!提前批!
查看>>
十分钟dva入门
查看>>
防止按钮重复点击
查看>>
Android SMSSDK无GUI接口集成方法
查看>>
Let's VUE[1]
查看>>
[-算法篇-] 排序
查看>>
实用贴:hadoop系统下载安装教程
查看>>
Apple正式生产AirPods 官方也将图片删除
查看>>
【云计算的1024种玩法】安装 MariaDB 并通过 DMS 管理
查看>>
Flutter UI APP 低调上线
查看>>
May-周记(2)
查看>>