tapable 监听函数执行compile 分析

401 阅读2分钟

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;
	}

---未完待续