tapable 监听函数执行compile 分析
1. header
// 对源代码进行一些改动 实现结果是一样的
// 1. 初始化函数执行参数
// 2. 执行intercepters
var context = {};
var _x = this._x;
var _taps = this._taps;
var _interceptors = this.interceptors;
_interceptors.forEach(t=>{
t.call && t.call(this.args({
before: t.context ? '_context' : 'undefined'
}))
})
2. create 方法
create(options) {
this.init(options);
let fn;
switch (this.options.type) {
case "sync":
fn = new Function(
this.args(),
'"use strict";\n' +
this.header() +
this.content({
onError: err => `throw ${err};\n`,
onResult: result => `return ${result};\n`,
onDone: () => "",
rethrowIfPossible: true
})
);
break;
case "async":
fn = new Function(
this.args({
after: "_callback"
}),
'"use strict";\n' +
this.header() +
this.content({
onError: err => `_callback(${err});\n`,
onResult: result => `_callback(null, ${result});\n`,
onDone: () => "_callback();\n"
})
);
break;
case "promise":
let code = "";
code += '"use strict";\n';
code += "return new Promise((_resolve, _reject) => {\n";
code += "var _sync = true;\n";
code += this.header();
code += this.content({
onError: err => {
let code = "";
code += "if(_sync)\n";
code += `_resolve(Promise.resolve().then(() => { throw ${err}; }));\n`;
code += "else\n";
code += `_reject(${err});\n`;
return code;
},
onResult: result => `_resolve(${result});\n`,
onDone: () => "_resolve();\n"
});
code += "_sync = false;\n";
code += "});\n";
fn = new Function(this.args(), code);
break;
}
this.deinit();
return fn;
}
3. sync
订阅函数重新新定义
content的具体内容实现上交给子类
同时注入 onError、OnResult、onDone、rethrowIfPossible(捕获异常, 重新丢出异常) 参数
fn = new Function(
this.args(),
'"use strict";\n' +
this.header() +
this.content({
onError: err => `throw ${err};\n`,
onResult: result => `return ${result};\n`,
onDone: () => "",
rethrowIfPossible: true
})
);
4. async
异步回调处理跟同步最大的区别就是函数结束用_callback()完成
fn = new Function(
this.args({
after: "_callback"
}),
'"use strict";\n' +
this.header() +
this.content({
onError: err => `_callback(${err});\n`,
onResult: result => `_callback(null, ${result});\n`,
onDone: () => "_callback();\n"
})
);
5. promise
promise 方式 返回一个 new Promise
let code = "";
code += '"use strict";\n';
code += "return new Promise((_resolve, _reject) => {\n";
code += "var _sync = true;\n";
code += this.header();
code += this.content({
onError: err => {
let code = "";
code += "if(_sync)\n";
code += `_resolve(Promise.resolve().then(() => { throw ${err}; }));\n`;
code += "else\n";
code += `_reject(${err});\n`;
return code;
},
onResult: result => `_resolve(${result});\n`,
onDone: () => "_resolve();\n"
});
code += "_sync = false;\n";
code += "});\n";
fn = new Function(this.args(), code);
6. content 方法实现 基础方法 callTap
callTap(tapIndex, { onError, onResult, onDone, rethrowIfPossible }) {
let code = "";
let hasTapCached = false;
// 执行interceptor 定义的tap 这块的应用 目前没有看到 后面源码分析到 在具体分析这块的设计初衷和使用场景
for (let i = 0; i < this.options.interceptors.length; i++) {
const interceptor = this.options.interceptors[i];
if (interceptor.tap) {
if (!hasTapCached) {
code += `var _tap${tapIndex} = ${this.getTap(tapIndex)};\n`;
hasTapCached = true;
}
code += `${this.getInterceptor(i)}.tap(${
interceptor.context ? "_context, " : ""
}_tap${tapIndex});\n`;
}
}
// _fn = tap函数
code += `var _fn${tapIndex} = ${this.getTapFn(tapIndex)};\n`;
const tap = this.options.taps[tapIndex];
switch (tap.type) {
case "sync":
// 如果不需要再次扔出异常 加入try -- catch
if (!rethrowIfPossible) {
code += `var _hasError${tapIndex} = false;\n`;
code += "try {\n";
}
// 如果函数有返回值 定义 _result
if (onResult) {
code += `var _result${tapIndex} = _fn${tapIndex}(${this.args({
before: tap.context ? "_context" : undefined
})});\n`;
} else {
// 不关心返回值 直接执行即可
code += `_fn${tapIndex}(${this.args({
before: tap.context ? "_context" : undefined
})});\n`;
}
// 不需要异常丢出 加入catch
if (!rethrowIfPossible) {
code += "} catch(_err) {\n";
code += `_hasError${tapIndex} = true;\n`;
code += onError("_err");
code += "}\n";
code += `if(!_hasError${tapIndex}) {\n`;
}
// 返回值 给onResult回调
if (onResult) {
code += onResult(`_result${tapIndex}`);
}
// onDone 完成回调
if (onDone) {
code += onDone();
}
if (!rethrowIfPossible) {
code += "}\n";
}
break;
// 异步执行
case "async":
let cbCode = "";
// 如果提供result 则定义有返回值的回调
if (onResult) cbCode += `(_err${tapIndex}, _result${tapIndex}) => {\n`;
// 如果没有返回值 定义只注入err参数的回调函数
else cbCode += `_err${tapIndex} => {\n`;
cbCode += `if(_err${tapIndex}) {\n`;
cbCode += onError(`_err${tapIndex}`);
cbCode += "} else {\n";
if (onResult) {
// 返回值给onResult函数
cbCode += onResult(`_result${tapIndex}`);
}
if (onDone) {
cbCode += onDone();
}
cbCode += "}\n";
cbCode += "}";
// 执行函数
code += `_fn${tapIndex}(${this.args({
before: tap.context ? "_context" : undefined,
after: cbCode
})});\n`;
break;
// promise 方式
case "promise":
code += `var _hasResult${tapIndex} = false;\n`;
// 执行fn 返回promise
code += `var _promise${tapIndex} = _fn${tapIndex}(${this.args({
before: tap.context ? "_context" : undefined
})});\n`;
// 如果不是promise 返回错误
code += `if (!_promise${tapIndex} || !_promise${tapIndex}.then)\n`;
code += ` throw new Error('Tap function (tapPromise) did not return promise (returned ' + _promise${tapIndex} + ')');\n`;
code += `_promise${tapIndex}.then(_result${tapIndex} => {\n`;
code += `_hasResult${tapIndex} = true;\n`;
// 返回result
if (onResult) {
code += onResult(`_result${tapIndex}`);
}
if (onDone) {
code += onDone();
}
// 异常回调
code += `}, _err${tapIndex} => {\n`;
code += `if(_hasResult${tapIndex}) throw _err${tapIndex};\n`;
code += onError(`_err${tapIndex}`);
code += "});\n";
break;
}
return code;
}
刚才分析了 生成监听函数 执行方式的最基础框架 下面具体分析串行、并行、循环的执行模式
7. callTapsSeries 串行执行
callTapsSeries({ onError, onResult, onDone, rethrowIfPossible }) {
if (this.options.taps.length === 0) return onDone();
// 获取第一个非同步监听下标
const firstAsync = this.options.taps.findIndex(t => t.type !== "sync");
const next = i => {
if (i >= this.options.taps.length) {
return onDone();
}
// 完成函数去调用下一次 next
const done = () => next(i + 1);
//中断执行函数
const doneBreak = skipDone => {
if (skipDone) return "";
return onDone();
};
//调用callTap 方法
return this.callTap(i, {
onError: error => onError(i, error, done, doneBreak),
onResult:
onResult &&
(result => {
return onResult(i, result, done, doneBreak);
}),
onDone:
!onResult &&
(() => {
return done();
}),
rethrowIfPossible:
rethrowIfPossible && (firstAsync < 0 || i < firstAsync)
});
};
// 递归调用
return next(0);
}
}
串行方法 没有任何特殊注意的地方 就是将taps 数组进行递归遍历调用 callTap生成code 将code 传给 content 方法 content 将code内容 再给 create 方法组装生成 可执行函数
create->content-> callTapsSeries -> callTap -> content->create-> call(this)
8. 循环调用callTapsLooping
// 循环调用
/***
var _loop;
do {
_loop = false;
var _fn0 = _x[0];
var _result0 = _fn0(name);
if(_result0 !== undefined) {
_loop = true;
} else {
if(!_loop) {
}
}
} while(_loop);
*/
callTapsLooping({ onError, onDone, rethrowIfPossible }) {
//如果没有taps 直接结束
if (this.options.taps.length === 0) return onDone();
// 是否全部是同步
const syncOnly = this.options.taps.every(t => t.type === "sync");
let code = "";
// 非全部同步
if (!syncOnly) {
code += "var _looper = () => {\n";
code += "var _loopAsync = false;\n";
}
code += "var _loop;\n";
code += "do {\n";
// loop设置为false
code += "_loop = false;\n";
for (let i = 0; i < this.options.interceptors.length; i++) {
const interceptor = this.options.interceptors[i];
if (interceptor.loop) {
code += `${this.getInterceptor(i)}.loop(${this.args({
before: interceptor.context ? "_context" : undefined
})});\n`;
}
}
// 调用串行方法
code += this.callTapsSeries({
onError,
onResult: (i, result, next, doneBreak) => {
let code = "";
// 如果返回值不是undefined 继续执行loop 否则就中断
code += `if(${result} !== undefined) {\n`;
code += "_loop = true;\n";
// 如果是异步 就会递归调用
if (!syncOnly) code += "if(_loopAsync) _looper();\n";
// 中断执行
code += doneBreak(true);
code += `} else {\n`;
// 继续执行
code += next();
code += `}\n`;
return code;
},
onDone:
onDone &&
(() => {
let code = "";
// loop 为false 调用结束onDone
code += "if(!_loop) {\n";
code += onDone();
code += "}\n";
return code;
}),
rethrowIfPossible: rethrowIfPossible && syncOnly
});
code += "} while(_loop);\n";
if (!syncOnly) {
code += "_loopAsync = true;\n";
code += "};\n";
code += "_looper();\n";
}
return code;
}
---未完待续