Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tapable-插件系统 #3

Open
791045873 opened this issue Nov 22, 2018 · 1 comment
Open

Tapable-插件系统 #3

791045873 opened this issue Nov 22, 2018 · 1 comment

Comments

@791045873
Copy link
Owner

Tapable这个库有两个代码版本,其中0.2版本更易理解,源码也更简单。先对0.2版本的源码与功能做一个介绍,然后再去看1.1.0版本的代码。

Tapable 0.2版本

该版本的源码结构非常简单。
一个简单的构造函数,原型上有着提供给我们使用的工具方法。

function Tapable() {
	this._plugins = {};
}
Tapable.prototype.applyPlugins = function (){ }
Tapable.prototype.applyPluginsWaterfall = function (){ }
// .....
// 等等

原型上的方法按照功能分为三种类型,分别是:注册,调用,判断。

注册

Tapable.prototype.plugin = function plugin(name, fn) {
	if(Array.isArray(name)) {
		name.forEach(function(name) {
			this.plugin(name, fn);
		}, this);
		return;
	}
	if(!this._plugins[name]) this._plugins[name] = [fn];
	else this._plugins[name].push(fn);
};

这里的name参数,用来表示这一类回调函数的作用。例如,在一个ajax的库中,你想要为每一个请求添加一系列的会在请求结束调用的方法。我们为这一系列的方法取名为endPoint,则注册的时候,就把endPoint作为参数name传入。
最终,会把所有注册的方法储存在实例的_plugin属性上,等待调用。

调用

Tapable里用于调用方法的api,只关注同一系列方法被调用时的状态,不关注不同系列方法是如何被调用的。因为,不同系列方法的调用,其实是属于我们的业务代码范畴。
即,不同系列(不在同一个name对应的方法数组里)的方法,其实是在处理着不同的情况。而两种不同情况如何衔接,应当是业务范畴。ps:一开始没搞清这个道理,一直想用Tapable的api去处理衔接逻辑。

Tapable的调用方法有很多,但是其实大部分是相同的。每一个调用方法的函数名后的数字,代表这个api在调用注册方法时可以向被调用的注册方法传递几个参数。应当是一种优化手段。
下面看一下大概的几个调用方式:

  • applyPlugins:该api仅顺序调用注册方法。
  • applyPluginsWaterfall:顺序调用注册方法,但是上一个方法的返回值会作为参数传入下一个方法
  • applyPluginsAsync:顺序调用注册的异步方法,且只当上一个方法结束后才会进行下一个方法。当所有方法均结束后,调用callback方法。
  • applyPluginsBailResult:顺序调用注册的同步方法,如果该方法有返回值,则调用callback,停止对其他注册方法的调用。
  • applyPluginsAsyncWaterfall:顺序调用注册的异步方法,且上一个方法的返回值会作为参数传给下一个要被调用的异步方法中,最后调用callback函数。如果中途抛出错误,则将错误传递给callback函数处理,之后的所有异步方法不再调用。
  • applyPluginsAsyncSeries:顺序调用注册的异步方法,且只当上一个方法结束后才会进行下一个方法。
  • applyPluginsParallel:顺序调用注册的方法,当所有方法正常结束后,调用callback
  • applyPluginsParallelBailResult:顺序调用注册的方法,且每一个方法结束时都必须调用回调callback。(这个方法的具体功效我并未看懂)

由以上api的梳理,我们大概可以看出来。api所做的工作,其实就是挨个调用注册方法(是否阻塞,是否传递返回值,是否竞争)。其中,竞争,阻塞,返回值等特殊处理,均是通过callback函数实现的。而我们储存进_plugin的方法,也必须有对应callback的接口。并没有什么黑魔法可以实现这些东西。

@791045873
Copy link
Owner Author

贴一个方法的源码,大概就可以看出来是如何让异步函数同步执行了。说白了还是用回调~还是需要前一个异步方法在回调中触发下一个异步方法

Tapable.prototype.applyPluginsAsyncSeries = Tapable.prototype.applyPluginsAsync = function applyPluginsAsyncSeries(name) {
	var args = Array.prototype.slice.call(arguments, 1);
	var callback = args.pop();
	var plugins = this._plugins[name];
	if(!plugins || plugins.length === 0) return callback();
	var i = 0;
	var _this = this;
	args.push(copyProperties(callback, function next(err) {
		if(err) return callback(err);
		i++;
		if(i >= plugins.length) {
			return callback();
		}
		plugins[i].apply(_this, args);
	}));
	plugins[0].apply(this, args);
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant