webpack4.X之tapable实例对象AsyncParallelHook源码
模拟手写AsyncParallelHook源码部分。
let Hook = require('./Hook.js')
class HookCodeFactory {
args({ after, before } = {}) {
let allArgs = this.options.args
if (before) allArgs = [before].concat(allArgs)
if (after) allArgs = allArgs.concat(after)
return allArgs.join(',') // ["name", "age"]===> name, age
}
head() {
return `"use strict";var _context;var _x = this._x;`
}
content() {
let code = `var _counter = ${this.options.taps.length};var _done = (function () {
_callback();
});`
for (var i = 0; i < this.options.taps.length; i++) {
code += `var _fn${i} = _x[${i}];_fn${i}(name, age, (function () {
if (--_counter === 0) _done();
}));`
}
return code
}
setup(instance, options) { // 先准备后续需要使用到的数据
this.options = options // 这里的操作在源码中是通过 init 方法实现,而我们当前是直接挂在了 this 身上
instance._x = options.taps.map(o => o.fn) // this._x = [f1, f2, ....]
}
create() { // 核心就是创建一段可执行的代码体然后返回
let fn
// fn = new Function("name, age", "var _x = this._x, var _fn0 = _x[0]; _fn0(name, age);")
fn = new Function(
this.args({ after: '_callback' }),
this.head() + this.content()
)
return fn
}
}
let factory = new HookCodeFactory()
class AsyncParallelHook extends Hook {
constructor(args) {
super(args)
}
compile(options) { // {taps: [{}, {}], args: [name, age]}
factory.setup(this, options)
return factory.create(options)
}
}
module.exports = AsyncParallelHook
class Hook { constructor(args = []) { this.args = args this.taps = [] // 将来用于存放组装好的 {} this._x = undefined // 将来在代码工厂函数中会给 _x = [f1, f2, f3....] } tap(options, fn) { if (typeof options === 'string') { options = { name: options } } options = Object.assign({ fn }, options) // { fn:... name:fn1 } // 调用以下方法将组装好的 options 添加至 [] this._insert(options) } tapAsync(options, fn) { if (typeof options === 'string') { options = { name: options } } options = Object.assign({ fn }, options) // { fn:... name:fn1 } // 调用以下方法将组装好的 options 添加至 [] this._insert(options) } _insert(options) { this.taps[this.taps.length] = options } call(...args) { // 01 创建将来要具体执行的函数代码结构 let callFn = this._createCall() // 02 调用上述的函数(args传入进去) return callFn.apply(this, args) } callAsync(...args) { let callFn = this._createCall() return callFn.apply(this, args) } _createCall() { return this.compile({ taps: this.taps, args: this.args }) } } module.exports = Hook
const SyncHook=require('./AsyncParallelHook.js')
//const { AsyncParallelHook } =require('tapable')
let hook=new AsyncParallelHook(["name","age"])
hook.tapAsync('fn1',function(name,age,callback){
console.log('fn1--->',name,age)
callback()
})
hook.tapAsync('fn2',function(name,age,callback){
console.log('fn2--->',name,age)
callback()
})
hook.callAsync('lw',18,function(){
console.log('end...')
})
---感谢阅读,o(* ̄︶ ̄*)o开心每一天!
posted on 2021-03-01 23:36 メSerendipity 阅读(133) 评论(0) 收藏 举报
浙公网安备 33010602011771号