[webpack]深入学习webpack核心模块tapable

一、手动实现同步钩子函数
1、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('react',function (name) {
console.log('react',name)
});
hook.tap('node',function (name) {
console.log('node',name)
});
hook.call('dellyoung');
2、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)=>{
// a 上一个 b 下一个
return b(a);
},ret
)
}
}
// 绑定事件就是订阅
let hook = new SyncWaterfallHook(['name']);
hook.tap('react',function (name) {
console.log('react1',name);
return 'reactOk'
});
hook.tap('node',function (name) {
console.log('node2',name);
return 'nodeOk'
});
hook.tap('webpack',function (name) {
console.log('webpack',name)
});
hook.call('dellyoung');
3、SyncLoopHook
class SyncLoopHook {
// 钩子是同步的
// 只要返回不是undefined就会一直循环
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('react',function (name) {
console.log('react',name);
return ++total === 3?undefined:'继续学'
});
hook.tap('node',function (name) {
console.log('node',name);
});
hook.tap('webpack',function (name) {
console.log('webpack',name)
});
hook.call('dellyoung');
4、SyncBailHook
class SyncBailHook {
// 钩子是同步的
constructor(args){
this.tasks = [];
}
tap(name,task){
this.tasks.push(task)
}
call(...args){
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('react',function (name) {
console.log('react1',name);
// return '停止'
});
hook.tap('node',function (name) {
console.log('node2',name)
});
hook.call('dellyoung');
二、手动实现异步钩子函数
1、AsyncParallelBailHook
类似promise.all[]
class AsyncParallelBailHook {
// 钩子是同步的
// 只要返回不是undefined就会一直循环
constructor(args){
this.tasks = [];
}
tapAsync(name,task){
this.tasks.push(task)
}
callAsync(...args){
let finalCallBack = args.pop(); // 拿出最终的函数
let index = 0;
let done = () => {
index++;
if(index === this.tasks.length){
finalCallBack();
}
};
this.tasks.forEach(task=>{
task(...args,done)
})
}
}
// 绑定事件就是订阅
let hook = new AsyncParallelBailHook(['name']);
hook.tapAsync('react',function (name,callback) {
setTimeout(()=>{
console.log('react',name);
callback();
},5000
);
});
hook.tapAsync('node',function (name,callback) {
setTimeout(()=>{
console.log('node',name);
callback();
},1000
);
});
hook.callAsync('dellyoung',function () {
console.log('newBegin')
});
promise版本的AsyncParallelBailHook
class AsyncParallelBailHook {
// 钩子是同步的
// 只要返回不是undefined就会一直循环
constructor(args) {
this.tasks = [];
}
tabPromise(name, task) {
this.tasks.push(task)
}
promise(...args) {
let tasks = this.tasks.map(
(task) => {
return task(...args)
}
);
// let tasks = this.tasks.map(task => task(...args));
return Promise.all(tasks);
}
}
// 绑定事件就是订阅
let hook = new AsyncParallelBailHook(['name']);
hook.tabPromise('react', function (name) {
return new Promise(
(resolve, reject) => {
setTimeout(() => {
console.log('react', name);
resolve();
}, 1000
);
}
)
});
hook.tabPromise('node', function (name) {
return new Promise(
(resolve, reject) => {
setTimeout(() => {
console.log('node', name);
resolve();
}, 2000
);
}
)
});
hook.promise('dellyoung').then(function () {
console.log('newBegin')
});
2、AsyncSeriesHook
异步串行
class AsyncSeriesHook {
constructor(args) {
this.tasks = [];
}
tabAsync(name, task) {
this.tasks.push(task)
}
callAsync(...args) {
let finalCallBack = args.pop();
let index = 0;
let next = () => {
if(this.tasks.length === index){
return finalCallBack();
}
let task = this.tasks[index++];
task(...args, next);
};
next();
}
}
// 绑定事件就是订阅
let hook = new AsyncSeriesHook(['name']);
hook.tabAsync('react', function (name, callback) {
setTimeout(() => {
console.log('react', name);
callback();
}, 3000
);
});
hook.tabAsync('node', function (name, callback) {
setTimeout(() => {
console.log('node', name);
callback();
}, 1000
)
});
hook.callAsync('dellyoung',function () {
console.log('newBegin')
});
promise版本的AsyncSeriesHook
class AsyncSeriesHook {
constructor(args) {
this.tasks = [];
}
tabPromise(name, task) {
this.tasks.push(task)
}
promise(...args) {
// 类redux源码
let [first,...other] = this.tasks;
return other.reduce(
(prom,n)=>{
return prom.then(()=>n(...args))
},first(...args)
)
}
}
// 绑定事件就是订阅
let hook = new AsyncSeriesHook(['name']);
hook.tabPromise('react', function (name) {
return new Promise(
(resolve, reject) => {
setTimeout(() => {
console.log('react', name);
resolve();
}, 1000
);
}
)
});
hook.tabPromise('node', function (name) {
return new Promise(
(resolve, reject) => {
setTimeout(() => {
console.log('node', name);
resolve();
}, 1000
);
}
)
});
hook.promise('dellyoung').then(function () {
console.log('newBegin')
});
3、AsyncSeriesWaterfallHook
异步瀑布串行
class AsyncSeriesWaterfallHook {
constructor(args) {
this.tasks = [];
}
tapAsync(name, task) {
this.tasks.push(task)
}
callAsync(...args) {
let finalCb = args.pop();
let index = 0;
let next = (err,data) => {
let task = this.tasks[index];
if(!task) return finalCb();
if(err) return ;
if(index===0){
// 执行第一个
task(...args,next)
}else {
task(data,next)
}
index++;
};
next()
}
}
// 绑定事件就是订阅
let hook = new AsyncSeriesWaterfallHook(['name']);
hook.tapAsync('react', function (name, cb) {
setTimeout(() => {
console.log('react', name);
cb(null, 'result1');
}, 1000
);
});
hook.tapAsync('node', function (data, cb) {
setTimeout(() => {
console.log('node', data);
cb(null);
}, 2000
);
});
hook.callAsync('dellyoung',function () {
console.log('newBegin')
});
[webpack]深入学习webpack核心模块tapable的更多相关文章
- Webpack 核心模块 tapable 解析(转)
原文出自:https://www.pandashen.com 前言 Webpack 是一个现代 JavaScript 应用程序的静态模块打包器,是对前端项目实现自动化和优化必不可少的工具,We ...
- webpack核心模块tapable用法解析
前不久写了一篇webpack基本原理和AST用法的文章,本来想接着写webpack plugin的原理的,但是发现webpack plugin高度依赖tapable这个库,不清楚tapable而直接去 ...
- webpack核心模块tapable源码解析
上一篇文章我写了tapable的基本用法,我们知道他是一个增强版版的发布订阅模式,本文想来学习下他的源码.tapable的源码我读了一下,发现他的抽象程度比较高,直接扎进去反而会让人云里雾里的,所以本 ...
- webpack4核心模块tapable源码解析
_ 阅读目录 一:理解Sync类型的钩子 1. SyncHook.js 2. SyncBailHook.js 3. SyncWaterfallHook.js 4. SyncLoopHook.js 二: ...
- 深入学习webpack(一)
深入学习webpack(一) 模块化的相关库和工具已经很多了,包括require.js.sea.js和一些工程化工具webpack.gulp.grant.那么我们该如何选择呢? 其实,我们只需要掌握了 ...
- 深入学习webpack(二)
深入学习webpack(二) 在深入学习webpack(一)中,我通过一个例子介绍了webpack的基本使用方法,下面将更为系统的学习webpack的基本概念,对于一门技术的掌握我认为系统化还是很重要 ...
- webpack入门学习手记(一)
本人微信公众号:前端修炼之路,欢迎关注. 之前用过gulp.grunt,但是一直没有学习过webpack.这两天刚好有时间,学习了下webpack.webpack要想深入研究,配置的东西比较多,网上的 ...
- WebPack 简明学习教程
WebPack 简明学习教程 字数1291 阅读22812 评论11 喜欢35 WebPack是什么 一个打包工具 一个模块加载工具 各种资源都可以当成模块来处理 网站 http://webpack. ...
- webpack的学习
什么是webpack? 他有什么优点? 首先对于很多刚接触webpack人来说,肯定会问webpack是什么?它有什么优点?我们为什么要使用它?带着这些问题,我们来总结下如下: Webpack是前端一 ...
随机推荐
- Python使用xlrd、pandas包从Excel读取数据
#coding=utf-8 # pip install xlrd import xlrd def read_from_xls(filepath,index_col_list): #filepath:读 ...
- SpringBoot配置HTTPS,并实现HTTP访问自动转HTTPS访问
[转]https://www.jianshu.com/p/8d4aba3b972d 推荐使用nginx配置https,因本文产生的任何问题不再做回复. 这里说一下为什么写这篇文章,因为我也是一个Spr ...
- 【清北学堂】广州OI学习游记
\(Day~0\) 早上\(9\)点多才爬起来,然后水了道题. 下午从[数据删除]出发,颠簸了将近\(5\)个小时终于抵达广州. 一出地铁站--卧槽这天,卧槽这风,要下雨的节奏? 没过两分钟倾盆大雨. ...
- Java类与类之间的6种关系及uml表示
一.继承关系 继承指的是一个类(称为子类.子接口)继承另外的一个类(称为父类.父接口)的功能,并可以增加它自己的新功能的能力.在Java中继承关系通过关键字extends明确标识,在设计时一般没有争议 ...
- subline html5的快捷键
选择类 Ctrl+D 选中光标所占的文本,继续操作则会选中下一个相同的文本. Alt+F3 选中文本按下快捷键,即可一次性选择全部的相同文本进行同时编辑.举个栗子:快速选中并更改所有相同的变量名.函数 ...
- Airtest---UI自动化测试项目
Airtest Project是网易游戏团队新开源出来的一款用于UI自动化测试的项目. testerhome中的文档介绍:https://testerhome.com/topics/12486 官方链 ...
- 前端面试题-JavaScript
引用GitHub 上 ltadpoles的前端面试 https://github.com/ltadpoles 目录 1. JavaScript 有哪些数据类型 2. 怎么判断不同的JS数据类型 ...
- 007_Python3 字符串
字符串是 Python 中最常用的数据类型.我们可以使用引号( ' 或 " )来创建字符串. 创建字符串很简单,只要为变量分配一个值即可. 例如: var1 = 'Hello World!' ...
- vue文件夹上传源码
一. 功能性需求与非功能性需求 要求操作便利,一次选择多个文件和文件夹进行上传:支持PC端全平台操作系统,Windows,Linux,Mac 支持文件和文件夹的批量下载,断点续传.刷新页面后继续传输. ...
- Redis学习之一--基础知识
一.定义 REmote DIctionary Server(Redis) 是一个以字典结构存储数据的key-value存储系统:使用ANSI C语言编写.遵守BSD协议.支持网络.可基于内存亦可持久化 ...