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 API 文档及使用教程 #23

Open
noneven opened this issue Mar 30, 2018 · 0 comments
Open

Tapable API 文档及使用教程 #23

noneven opened this issue Mar 30, 2018 · 0 comments

Comments

@noneven
Copy link
Owner

noneven commented Mar 30, 2018

Tapable API 文档及使用教程

Tapable(0.2.x)

使用

import Tapable from 'tapable';
//var Tapable = require('tapable');

Tapable 是一个用于事件发布订阅执行的插件架构。
在使用时你仅仅需要像这样继承它:

function MyClass() {
  Tapable.call(this);
}
MyClass.prototype = Object.create(Tapable.prototype);

// 或者这样
function MyClass2() {
  Tapable.call(this);
}
Tapable.mixin(MyClass2.prototype);

// 或者这样
class MyClass3 extends Tapable {
  constructor() {
    // TODO
  }
}

API

静态方法(Static functions)

  • mixin
void mixin(obj: Object)

复制 Tapable 的原型方法到目标对象

实例公共方法(Public functions)

  • apply

插件加载函数

void apply(plugin1: Plugin, plugin2: Plugin...)

通过 arguments 获得所有传入的插件对象,并调用插件对象的 apply 方法,注册插件(所以,一个合法的插件应该包含入口方法 apply)

  • plugin

事件绑定函数,类似于 EventEmitter 的 on 方法

void plugin(names: string|string[], handler: Function)

names: 需要监听的事件名称,可以传入事件名称集合(同时绑定多个事件),也可以传入单个事件名称
handler: 事件的处理函数

例子1:

var Tapable = require('tapable');

function Compiler(plugins) {
  Tapable.call(this);
  // 注册插件
  this.apply(...plugins);
  // 编译器在某个异步操作完成后触发事件
  setTimeout(() => {
    // 触发事件
    this.applyPlugins('compiled', 'test');
  }, 4000);
}
Compiler.prototype = Object.create(Tapable.prototype);

function CustomPlugin() {}
CustomPlugin.prototype.apply = function (compiler) {
  // 注册插件时会调用插件的 apply 方法,会执行绑定插件
  compiler.plugin('compiled', (arg) => {
    console.log('arg:', arg); // arg: test
  });
};

new Compiler([new CustomPlugin()]);

实例受保护方法(Protected functions)

  • applyPlugins

类似 EventEmitter 的 emit 方法,使用实例见例子1

void applyPlugins(name: string, args: any...)

触发事件 name,传入参数 args,并行调用所有注册在事件 name 上的处理函数。

  • applyPluginsWaterfall
any applyPluginsWaterfall(name: string, init: any, args: any...)

触发事件 name,串行的调用注册在事件 name 上的处理函数(先入先出),最先执行的处理函数传入 init 和 args,后续的处理函数传入前一个处理函数的返回值和 args,函数最终返回最后一个处理函数的返回结果
例子2:【后面的例子可以由这个例子修改观察结果】

var Tapable = require('tapable');

function Compiler(plugins) {
  Tapable.call(this);
  // 注册插件
  this.apply(...plugins);
  // 编译器在某个异步操作完成后触发事件
  setTimeout(() => {
    // 触发事件
    const afterPluginValue = this.applyPluginsWaterfall('compiled', 'InitValue');
    console.log('after all plugins value:', afterPluginValue);
  }, 4000);
}
Compiler.prototype = Object.create(Tapable.prototype);

function CustomPlugin() {}
CustomPlugin.prototype.apply = function (compiler) {
  // 注册插件时会调用插件的 apply 方法,会执行绑定插件
  compiler.plugin('compiled', (arg) => {
    console.log('in plugin value:', arg);
    // todo
    console.log('out plugin value:', 'PluginValue');
    return 'PluginValue';
  });
};
function CustomPlugin1() {}
CustomPlugin1.prototype.apply = function (compiler) {
  // 注册插件时会调用插件的 apply 方法,会执行绑定插件
  compiler.plugin('compiled', (arg) => {
    console.log('in plugin1 value::', arg);
    // todo
    console.log('out plugin1 value:', 'PluginValue1');
    return 'Plugin1Value';
  });
};

new Compiler([new CustomPlugin(), new CustomPlugin1()]);

// in plugin value: InitValue
// out plugin value: PluginValue
// in plugin1 value:: PluginValue
// out plugin1 value: PluginValue1
// after all plugins value: Plugin1Value
  • applyPluginsAsyncWaterfall
applyPluginsAsyncWaterfall(
  name: string,
  init: any,
  callback: (err: Error, result: any) -> void
)

触发事件 name,串行的调用注册在 name 上的处理函数(先入先出),第一个处理函数传入参数 init,后续的函数依赖于前一个函数执行回调的时候传入的参数nextValue,倘若某一个处理函数报错,则执行传入的 callback(err),后续的处理函数将不被执行,否则最后一个处理函数调用 callback(value)
注意:插件注册此类事件,处理函数需要调用 callback(err, nextValue),这样才能保证监听链的正确执行

var myPlugin = function() {}
myPlugin.prototype.apply(tapable) {
  tapable.plugin('name', function(arg1, ..., argn, callback)) {
    // todo
    // ...
    // 调用 callback
    callback(null, value);
  }
}
  • applyPluginsAsync = applyPluginsAsyncSeries
void applyPluginsAsync(
  name: string,
  args: any...,
  callback: (err?: Error) -> void
)

触发事件 name,串行的调用注册在事件 name 上的处理函数(先入先出),倘若某一个处理函数报错,则执行传入的 callback(err),后续的处理函数将不被执行,否则最后一个处理函数调用 callback。
注意:插件注册此类事件,处理函数需要调用callback,这样才能保证监听链的正确执行

var myPlugin = function() {}
myPlugin.prototype.apply(tapable) {
  tapable.plugin('name', function(arg1, ..., argn, callback)) {
    // todo
    // ...
    // 调用callback
    callback();
  }
}
  • applyPluginsBailResult
any applyPluginsBailResult(name: string, args: any...)

触发事件 name,串行的调用注册在事件 name 上的处理函数(先入先出),传入参数 args,如果其中一个处理函数返回值 !== undefined,直接返回这个返回值,后续的处理函数将不被执行

  • applyPluginsParallel
applyPluginsParallel(
  name: string,
  args: any...,
  callback: (err?: Error) -> void
)

触发事件 name,传入参数 args,并行的调用所有注册在事件 name 上的处理函数,倘若任一处理函数执行报错,则执行 callback('err'),否则当所有的处理函数都执行完的时候调用 callback()

同样,插件注册此类事件的时候,回调函数要执行 callback

  • applyPluginsParallelBailResult
applyPluginsParallelBailResult(
  name: string,
  args: any...,
  callback: (err: Error, result: any) -> void
)

触发事件 name,串行的执行注册在事件 name 上的处理函数(先入先出),每个处理函数必须调用 callback(err, result),倘若任一处理函数在调用callback(err, result) 的时候,err !== undefined || result !== undefined,则 callback 将真正被执行,后续的处理函数则不会再被执行。

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