- Hook 基類,負(fù)責(zé)通用方法實(shí)現(xiàn)
class Hook {
constructor(args = []) {
this.args = args
// 用于存儲(chǔ)所有的tap對(duì)象
this.taps = []
// 用于存儲(chǔ)所有的tap里面的fn
// 代碼工廠負(fù)責(zé)賦值
this._x = undefined
}
tap(option, fn) {
if (typeof option === 'string') {
option = {name: option}
}
// 合并
option = Object.assign({fn}, option)// { fn:... name:fn1 }
// 調(diào)用以下方法將組裝好的 options 添加至 []
this._insert(option)
}
call(...args) {
// 01 創(chuàng)建將來(lái)要具體執(zhí)行的函數(shù)代碼結(jié)構(gòu)
let callFn = this._createCall()
// 02 調(diào)用上述的函數(shù)(args傳入進(jìn)去)
return callFn.apply(this, args)
}
_createCall() {
return this.compile({
taps: this.taps,
args: this.args
})
}
_insert(options) {
this.taps[this.taps.length] = options
}
}
module.exports = Hook
- HookCodeFactory & SyncHook
HookCodeFactory 代碼構(gòu)建
SyncHook 子類
let Hook = require("./Hook.js")
class HookCodeFactory {
args() {
return this.options.args.join(',')
}
head() {
return 'var _x = this._x;'
}
content() {
let code = ''
for (let i = 0; i < this.options.taps.length; i++) {
code += `var _fn${i} = _x[${i}]; _fn${i}(${this.args()});`
}
return code;
}
init(options) {
this.options = options
}
// instance就是Hook
// options: {taps: [{}, {}], args: [name, age]}
setup(instance, options) {
// this._x = [f1, f2, ....]
instance._x = options.taps.map(o => o.fn)
}
// 核心就是創(chuàng)建一段可執(zhí)行的代碼體然后返回
create(options) {
this.init(options)
let fn
// fn = new Function("name, age", "var _x = this._x, var _fn0 = _x[0]; _fn0(name, age);")
fn = new Function(
this.args(),
this.head() + this.content()
)
return fn
}
}
let factory = new HookCodeFactory()
class SyncHook extends Hook {
constructor(args) {
super(args)
}
// {taps: [{}, {}], args: [name, age]}
compile(options) {
factory.setup(this, options)
return factory.create(options)
}
}
module.exports = SyncHook
- HookCodeFactory & AsyncParallelHook
AsyncParallelHook主要是要處理下callback
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) { // 先準(zhǔn)備后續(xù)需要使用到的數(shù)據(jù)
this.options = options // 這里的操作在源碼中是通過(guò) init 方法實(shí)現(xiàn),而我們當(dāng)前是直接掛在了 this 身上
instance._x = options.taps.map(o => o.fn) // this._x = [f1, f2, ....]
}
create() { // 核心就是創(chuàng)建一段可執(zhí)行的代碼體然后返回
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
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。