二十七、1.tapable介绍:Webpack核心Tapable,基于发布订阅原理
- 使用 1.start.js
let { SyncHook } = require('tapable');
class Lession{
constructor(){
this.hooks = {
arch: new SyncHook(['name']),
}
}
tap(){ // 注册监听函数
this.hooks.arch.tap('node',function(name){
console.log('node',name);
})
this.hooks.arch.tap('node',function(name){
console.log('react',name);
})
}
start(){
this.hooks.arch.call('kft');
}
}
let l = new Lession();
l.tap(); // 注册这两个事件
l.start(); // 启动钩子
- 2.case.js
class SyncHook { // 钩子
constructor(args) {
this.tasks = [];
}
call(...args) {
this.tasks.forEach((task) => task(...args));
}
tap(name, task) {
this.tasks.push(task);
}
}
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('kft');
二十八、2.tapable:同步钩子hook
- 同步钩子四方法:SyncHook/SyncBailHook/SyncWaterfallHook/SyncLoopHook
- SyncHook:tap注册所有事件,start启动执行所有事件
- SyncBailHook 保险hooks,如果return!==undefined,停止向下执行
let { SyncBailHook } = require('tapable');
class Lession{
constructor(){
this.hooks = {
arch: new SyncBailHook(['name']),
}
}
tap(){ // 注册监听函数
this.hooks.arch.tap('node',function(name){
console.log('node',name);
return '停止向下执行';
})
this.hooks.arch.tap('node',function(name){
console.log('react',name);
})
}
start(){
this.hooks.arch.call('kft');
}
}
let l = new Lession();
l.tap(); // 注册这两个事件
l.start(); // 启动钩子
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);
}
}
let hook = new SyncBailHook(['name']);
hook.tap('react', function (name) {
console.log('react', name);
return '停止向下执行';
})
hook.tap('node', function (name) {
console.log('node', name)
})
hook.call('kft');
- SyncWaterfallHook: 上下函数联系,流程控制
- SyncWaterfallHook.start.js
let { SyncWaterfallHook } = require('tapable');
class Lession{
constructor(){
this.hooks = {
arch: new SyncWaterfallHook(['name']),
}
}
tap(){ // 注册监听函数
this.hooks.arch.tap('node',function(name){
console.log('node',name);
return '停止向下执行';
})
this.hooks.arch.tap('node',function(name){
console.log('react',name);
})
}
start(){
this.hooks.arch.call('kft');
}
}
let l = new Lession();
l.tap(); // 注册这两个事件
l.start(); // 启动钩子
- SyncWaterfallHook.case.js 源码
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('react', function (name) {
console.log('react', name);
return 'reactok';
})
hook.tap('node', function (name) {
console.log('node', name)
return 'nodeok';
})
hook.tap('webpack', function (name) {
console.log('webpack', name)
return 'nodeok';
})
hook.call('kft');
- SyncLoopHook 遇到不返回undefined监听函数多次执行
let { SyncLoopHook } = require('tapable');
class Lession {
constructor() {
this.index = 0;
this.hooks = {
arch: new SyncLoopHook(['name']),
}
}
tap() { // 注册监听函数
this.hooks.arch.tap('node', (name) => {
console.log('node', name);
return ++this.index === 3 ? undefined : '继续执行当前函数';
})
this.hooks.arch.tap('node', (name) => {
console.log('react', name);
})
}
start() {
this.hooks.arch.call('kft');
}
}
let l = new Lession();
l.tap(); // 注册这两个事件
l.start(); // 启动钩子
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('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('kft');
二十九、3.AsyncParallelHook:异步并行钩子
- 异步钩子分为串行、并行,并行钩子需要等待所有并发的异步事件执行后在执行回调方法;
- AsyncParallelHook callAsync tapAsync cb() promise tapPromise then
let { AsyncParallelHook } = require('tapable');
class Lession {
constructor() {
this.hooks = {
arch: new AsyncParallelHook(['name']),
}
}
tap() { // 注册监听函数
this.hooks.arch.tapAsync('node', function (name, cb) {
setTimeout(() => {
console.log('node', name);
cb();
}, 1000)
})
this.hooks.arch.tapAsync('node', function (name, cb) {
setTimeout(() => {
console.log('react', name);
cb();
}, 1000)
})
}
start() {
this.hooks.arch.callAsync('kft', function () {
console.log('end');
});
}
}
let l = new Lession();
l.tap(); // 注册这两个事件
l.start(); // 启动钩子
class AsyncParallelHook { // 钩子
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 AsyncParallelHook(['name']);
hook.tapAsync('react', function (name, cb) {
setTimeout(() => {
console.log('react', name);
cb();
})
})
hook.tapAsync('node', function (name, cb) {
setTimeout(() => {
console.log('node', name);
cb();
})
})
hook.callAsync('kft', function () {
console.log('end');
});
- AsyncParrallelHook promise tapPromise then
let { AsyncParallelHook } = require('tapable');
class Lession {
constructor() {
this.hooks = {
arch: new AsyncParallelHook(['name']),
}
}
tap() { // 注册监听函数
this.hooks.arch.tapPromise('node', function (name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('node', name);
resolve();
}, 1000)
})
})
this.hooks.arch.tapPromise('react', function (name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('react', name);
resolve();
}, 1000)
})
})
}
start() {
this.hooks.arch.promise('kft').then(function(data){
console.log('end');
})
}
}
let l = new Lession();
l.tap(); // 注册这两个事件
l.start(); // 启动钩子
class AsyncParallelHook { // 钩子
constructor(args) {
this.tasks = [];
}
tapPromise(name, task) {
this.tasks.push(task);
}
promise(...args) {
let tasks = this.tasks.map(task => task(...args));
return Promise.all(tasks);
}
}
let hook = new AsyncParallelHook(['name']);
hook.tapPromise('react', function (name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('react', name);
resolve();
}, 1000)
})
})
hook.tapPromise('node', function (name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('node', name);
resolve();
}, 1000)
})
})
hook.promise('kft').then(function () {
console.log('end');
})
三十、4. AsyncSeriesHook:异步串行钩子
- AsyncSeriesHook tapAsync callAsync 1-2-end
let { AsyncSeriesHook } = require('tapable');
class Lession {
constructor() {
this.hooks = {
arch: new AsyncSeriesHook(['name']),
}
}
tap() { // 注册监听函数
this.hooks.arch.tapAsync('node', function (name, cb) {
setTimeout(() => {
console.log('node', name);
cb();
}, 1000)
})
this.hooks.arch.tapAsync('react', function (name, cb) {
setTimeout(() => {
console.log('react', name);
cb();
}, 1000)
})
}
start() {
this.hooks.arch.callAsync('kft', function (data) {
console.log('end');
})
}
}
let l = new Lession();
l.tap(); // 注册这两个事件
l.start(); // 启动钩子
class AsyncSeriesHook { // 钩子
constructor(args) {
this.tasks = [];
}
tapAsync(name, task) {
this.tasks.push(task);
}
callAsync(...args) {
let index = 0;
let finalCallback = args.pop();
let next = () => {
if (index === this.tasks.length) {
return finalCallback();
}
let task = this.tasks[index++];
task(...args, next);
}
next(...args);
}
}
let hook = new AsyncSeriesHook(['name']);
hook.tapAsync('react', function (name, cb) {
setTimeout(() => {
console.log('react', name);
cb();
}, 1000)
})
hook.tapAsync('node', function (name, cb) {
setTimeout(() => {
console.log('node', name);
cb();
}, 1000)
})
hook.callAsync('kft', function () {
console.log('end');
})
- AsyncSeriesHook promise tapPromise
let { AsyncSeriesHook } = require('tapable');
class Lession {
constructor() {
this.hooks = {
arch: new AsyncSeriesHook(['name']),
}
}
tap() { // 注册监听函数
this.hooks.arch.tapPromise('node', function (name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('node', name);
resolve();
}, 1000)
})
})
this.hooks.arch.tapPromise('react', function (name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('react', name);
resolve();
}, 1000)
})
})
}
start() {
this.hooks.arch.promise('kft').then(function (data) {
console.log('end');
})
}
}
let l = new Lession();
l.tap(); // 注册这两个事件
l.start(); // 启动钩子
class AsyncSeriesHook { // 钩子
constructor(args) {
this.tasks = [];
}
tapPromise(name, task) {
this.tasks.push(task);
}
promise(...args) {
let [first, ...others] = this.tasks;
return others.reduce((p, n) => {
return p.then(() => n(...args));
}, first(...args));
}
}
let hook = new AsyncSeriesHook(['name']);
hook.tapPromise('react', function (name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('react', name);
resolve();
}, 1000)
})
})
hook.tapPromise('node', function (name) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('node', name);
resolve();
}, 1000)
})
})
hook.promise('kft').then(function () {
console.log('end');
})
三十一、5.AsyncSeriesWaterfallHook:异步串行瀑布
- AsyncSeriesWaterfallHook tapAsync callAsync cb(null,'result')成功 cb('error','result')跳到最后结果
let { AsyncSeriesWaterfallHook } = require('tapable');
class Lession {
constructor() {
this.hooks = {
arch: new AsyncSeriesWaterfallHook(['name']),
}
}
tap() { // 注册监听函数
this.hooks.arch.tapAsync('node', function (name, cb) {
setTimeout(() => {
console.log('node', name);
cb('error','result');
}, 1000)
})
this.hooks.arch.tapAsync('react', function (name, cb) {
setTimeout(() => {
console.log('react', name);
cb();
}, 2000)
})
}
start() {
this.hooks.arch.callAsync('kft', function (data) {
console.log('end');
})
}
}
let l = new Lession();
l.tap(); // 注册这两个事件
l.start(); // 启动钩子
class AsyncSeriesWaterfallHook { // 钩子
constructor(args) {
this.tasks = [];
}
tapAsync(name, task) {
this.tasks.push(task);
}
callAsync(...args) {
let index = 0;
let finalCallback = args.pop();
let next = (err, data) => {
if (index === this.tasks.length) return finalCallback();
let task = this.tasks[index];
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,'react');
}, 1000)
})
hook.tapAsync('node', function (name, cb) {
setTimeout(() => {
console.log('node', name);
cb(null,'node');
}, 1000)
})
hook.callAsync('kft', function () {
console.log('end');
})