- SyncWaterfallHook表示如果上一个回调函数的结果不为undefined,则可以作为下一个回调函数的第一个参数
- 回调函数接受的参数来自于上一个函数的结果
- 调用call传入的第一个参数,会被上一个函数的非undefined结果替换
- 当回调函数返回非undefined不会停止回调栈的调用
使用:
const { SyncWaterfallHook } = require("tapable"); //所有的钩子构造函数, 都接受一个可选的参数, (这个参数最好是数组, 不是tapable内部也把他变成数组), 这是一个参数的字符串名字列表 //const hook = new SyncHook(["arg1", "arg2", "arg3"]); class lession { constructor() { //最好的实践就是把所有的钩子暴露在一个类的hooks属性里面: this.hooks = { arch: new SyncWaterfallHook(["name"]), } } // 注册监听函数 tap() { this.hooks.arch.tap('node', function (name) { console.log('node', name) return 'node学习的还可以' }) this.hooks.arch.tap('vue', function (name) { console.log('vue', name) }) } start() { this.hooks.arch.call('jw'); } } let ls = new lession(); //注册 ls.tap() //启动 ls.start()
原理:
class SyncWaterfallHook { constructor(args) { this.tasks = [] } tap(name, task) { this.tasks.push(task) } call(...args) { //解构 let [first, ...others] = this.tasks; // 第一个先执行 let ret = first(...args); // 迭代 // 传入返回值 // b 是回调函数 a 是name others.reduce((a, b) => { return b(a); }, ret) } } let hook = new SyncWaterfallHook(['name']); hook.tap('react', function (name) { console.log('react', name) return '学习了react' }) hook.tap('vue', function (data) { console.log('vue', data) return '学习了vue' }) hook.tap('node', function (data) { console.log('node', data) return '学习了node' }) hook.call('jw')