FE.SRC-webpack/tapable-0.2 源码分析
Tapable
https://github.com/webpack/ta...
https://segmentfault.com/a/11...
var Tapable = require("tapable");
Tapable
是一个用于插件绑定的类
继承方式1
function MyClass() { Tapable.call(this); } MyClass.prototype = Object.create(Tapable.prototype); MyClass.prototype.method = function() {};
继承方式2
function MyClass2() { EventEmitter.call(this); Tapable.call(this); } MyClass2.prototype = Object.create(EventEmitter.prototype); Tapable.mixin(MyClass2.prototype); MyClass2.prototype.method = function() {};
公有方法
apply
void apply(plugins: Plugin...)
通过调用apply
它们将作为参数传递的所有插件附加到实例。
plugin
void plugin(names: string|string[], handler: Function)
names
需要监听的事件名称,可以传入事件名称集合(同时绑定多个事件),也可以传入单个事件名称handler
事件的处理函数
私有方法
applyPlugins
void applyPlugins(name: string, args: any...)
同步调用所有的name插件,传入参数args,并行的调用所有注册在事件name上的处理函数。所有注册的处理方法并行执行,相互独立互不干扰。(根据传参格式内部提供了applyPlugins0,applyPlugins1,applyPlugins2)
function applyPlugins1(name, param) { var plugins = this._plugins[name]; if(!plugins) return; for(var i = 0; i < plugins.length; i++) plugins[i].call(this, param); };
applyPluginsWaterfall
any applyPluginsWaterfall(name: string, init: any, args: any...)
串行的调用所有的name插件,
第一个处理函数传入init和args,
后续的处理函数传入前一个处理函数的返回值和args,
最终返回最后一个处理函数的返回结果
(内部同样提供了012方法)
function applyPluginsWaterfall1(name, init, param) { var plugins = this._plugins[name]; if(!plugins) return init; var current = init; for(var i = 0; i < plugins.length; i++) current = plugins[i].call(this, current, param); return current; };
applyPluginsAsync | applyPluginsAsyncSeries
void applyPluginsAsync( name: string, args: any..., callback: (err?: Error) -> void )
异步调用所有的name插件(依次执行),倘若某一个处理函数报错,则执行传入的callback(err),后续的处理函数将不被执行,否则最后一个处理函数调用callback
function applyPluginsAsyncSeries1(name, param, callback) { var plugins = this._plugins[name]; if(!plugins || plugins.length === 0) return callback(); var i = 0; var _this = this; var innerCallback = copyProperties(callback, function next(err) { if(err) return callback(err); i++; if(i >= plugins.length) { return callback(); } plugins[i].call(_this, param, innerCallback); }); plugins[0].call(this, param, innerCallback); };
applyPluginsBailResult
any applyPluginsBailResult(name: string, args: any...)
同步调用所有的name插件,如果其中一个处理函数返回值!== undefined,直接返回这个返回值,后续的处理函数将不被执行
function applyPluginsBailResult1(name, param) { if(!this._plugins[name]) return; var plugins = this._plugins[name]; for(var i = 0; i < plugins.length; i++) { var result = plugins[i].call(this, param); if(typeof result !== "undefined") { return result; } } };
applyPluginsAsyncWaterfall
applyPluginsAsyncWaterfall( name: string, init: any, callback: (err: Error, result: any) -> void )
异步调用所有的name插件。后续的函数依赖于前一个函数执行回调的时候传入的参数nextValue(第一个处理函数传入参数init)。
倘若某一个处理函数报错,则执行传入的callback(err),后续的处理函数将不被执行,否则最后一个处理函数调用callback(value)。
function applyPluginsAsyncWaterfall(name, init, callback) { if(!this._plugins[name] || this._plugins[name].length === 0) return callback(null, init); var plugins = this._plugins[name]; var i = 0; var _this = this; var next = copyProperties(callback, function(err, value) { if(err) return callback(err); i++; if(i >= plugins.length) { return callback(null, value); } plugins[i].call(_this, value, next); }); plugins[0].call(this, init, next); };
applyPluginsParallel
applyPluginsParallel( name: string, args: any..., callback: (err?: Error) -> void )
并行的调用所有注册在事件name上的处理函数,倘若任一处理函数执行报错,则执行callback('err'),否则当所有的处理函数都执行完的时候调用callback()
function applyPluginsParallel(name) { var args = Array.prototype.slice.call(arguments, 1); var callback = args.pop(); if(!this._plugins[name] || this._plugins[name].length === 0) return callback(); var plugins = this._plugins[name]; var remaining = plugins.length; args.push(copyProperties(callback, function(err) { if(remaining < 0) return; // ignore if(err) { remaining = -1; return callback(err); } remaining--; if(remaining === 0) { return callback(); } })); for(var i = 0; i < plugins.length; i++) { plugins[i].apply(this, args); if(remaining < 0) return; } };
applyPluginsParallelBailResult
applyPluginsParallelBailResult( name: string, args: any..., callback: (err: Error, result: any) -> void )
并行调用,每个处理函数必须调用callback(err, result),
倘若任一处理函数在调用callback(err, result)的时候,err!==undefined || result!==undefined,则callback将真正被执行,后续的处理函数则不会再被执行。
顺序由注册插件顺序决定,而不是由函数的执行时间。
applyPluginsParallelBailResult1(name, param, callback) { var plugins = this._plugins[name]; if(!plugins || plugins.length === 0) return callback(); var currentPos = plugins.length; var currentResult; var done = []; for(var i = 0; i < plugins.length; i++) { var innerCallback = (function(i) { return copyProperties(callback, function() { if(i >= currentPos) return; // ignore done.push(i); if(arguments.length > 0) { currentPos = i + 1; done = fastFilter.call(done, function(item) { return item <= i; }); currentResult = Array.prototype.slice.call(arguments); } if(done.length === currentPos) { callback.apply(null, currentResult); currentPos = 0; } }); }(i)); plugins[i].call(this, param, innerCallback); } };
hasPlugins
hasPlugins( name: string )
如果为此名称注册了插件,则返回true。