一、手动实现同步钩子函数

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的更多相关文章

  1. Webpack 核心模块 tapable 解析(转)

        原文出自:https://www.pandashen.com 前言 Webpack 是一个现代 JavaScript 应用程序的静态模块打包器,是对前端项目实现自动化和优化必不可少的工具,We ...

  2. webpack核心模块tapable用法解析

    前不久写了一篇webpack基本原理和AST用法的文章,本来想接着写webpack plugin的原理的,但是发现webpack plugin高度依赖tapable这个库,不清楚tapable而直接去 ...

  3. webpack核心模块tapable源码解析

    上一篇文章我写了tapable的基本用法,我们知道他是一个增强版版的发布订阅模式,本文想来学习下他的源码.tapable的源码我读了一下,发现他的抽象程度比较高,直接扎进去反而会让人云里雾里的,所以本 ...

  4. webpack4核心模块tapable源码解析

    _ 阅读目录 一:理解Sync类型的钩子 1. SyncHook.js 2. SyncBailHook.js 3. SyncWaterfallHook.js 4. SyncLoopHook.js 二: ...

  5. 深入学习webpack(一)

    深入学习webpack(一) 模块化的相关库和工具已经很多了,包括require.js.sea.js和一些工程化工具webpack.gulp.grant.那么我们该如何选择呢? 其实,我们只需要掌握了 ...

  6. 深入学习webpack(二)

    深入学习webpack(二) 在深入学习webpack(一)中,我通过一个例子介绍了webpack的基本使用方法,下面将更为系统的学习webpack的基本概念,对于一门技术的掌握我认为系统化还是很重要 ...

  7. webpack入门学习手记(一)

    本人微信公众号:前端修炼之路,欢迎关注. 之前用过gulp.grunt,但是一直没有学习过webpack.这两天刚好有时间,学习了下webpack.webpack要想深入研究,配置的东西比较多,网上的 ...

  8. WebPack 简明学习教程

    WebPack 简明学习教程 字数1291 阅读22812 评论11 喜欢35 WebPack是什么 一个打包工具 一个模块加载工具 各种资源都可以当成模块来处理 网站 http://webpack. ...

  9. webpack的学习

    什么是webpack? 他有什么优点? 首先对于很多刚接触webpack人来说,肯定会问webpack是什么?它有什么优点?我们为什么要使用它?带着这些问题,我们来总结下如下: Webpack是前端一 ...

随机推荐

  1. ansible自动化部署之场景应用

    ansible自动化配置管理 官方网站: https://docs.ansible.com 一.安装 配置 启动 (ansible由红帽收购) (1)什么是ansible ansible是IT自动化配 ...

  2. 【深度学习】Precision 和 Recall 评价指标理解

    1. 四种情况 Precision精确率, Recall召回率,是二分类问题常用的评价指标.混淆矩阵如下: 预测结果为阳性 Positive 预测结果为假阳性 Negative 预测结果是真实的 Tr ...

  3. Codeforces Round #510 (Div. 2) C. Array Product

    题目 题意: 给你n个数,有两种操作,操作1是把第i个位置的数删去, 操作2 是把 a[ j ]= a[ i ]* a[ j ],把a[ i ]删去 .n-1个操作以后,只剩1个数,要使这个数最大 . ...

  4. H5s播放rtsp和rtmp视频

    最近接触的几个项目都有对接视频的功能,目前国内视频厂商以海康和大华为主,其对应的视频流格式也不一致,导致对接起来很麻烦.有幸在客户那接触到一种新的视频对接解决方案,支持Html5标准.废话不多少,看一 ...

  5. VFD 时钟(VFD Clock with STM8 v2.0)

    算是填了最先挖的VFD坑 最近pcb厂家神仙打架,为PCB普及做出了巨大贡献,到这事儿发生我也就开了两三次板,都赶上这个时间了,不开白不开! 不说了,上图! sch: pcb: 方案和之前的除了驱动电 ...

  6. javaScript基础及初始面向对象

    对象是什么?对象是包含相关属性和方法的集合体属性方法什么是面向对象面向对象仅仅是一个概念或者编程思想通过一种叫做原型的方式来实现面向对象编程 创建对象自定义对象内置对象 自定义对象2-1基于Objec ...

  7. Linq找不到行或行已更改

    1.发生这种情况第一时间是确认了database明明存在这条数据 2.然后确认了Linq查找的条件中是否有连接条件使得连续更新中发生变化 3.最后发现原来是Linq使用的表实际中有个field由not ...

  8. SpringBoot监控中心

    1.什么是SpringBoot监控中心? 2.为什么要使用SpringBoot监控中心?

  9. Xmind8安装

    现在新版安装极其简单.是deb安装包Xmind8安装小书匠 kindle 参照官网安装方法,在此记录下来,方便自己查找. 流程: 55ccaad0655d256ac5fb9fea8aa8569d.pn ...

  10. spring boot aop 切库实现读写分离

    项目结构: 主要代码 : 配置数据库 配置datasource 线程隔离: 已上传git gitee地址:https://gitee.com/xxoo0_297/springboot-aop.git