{"action":"opened","issue":{"url":"https://api.github.com/repos/coderwin/__/issues/23","repository_url":"https://api.github.com/repos/coderwin/__","labels_url":"https://api.github.com/repos/coderwin/__/issues/23/labels{/name}","comments_url":"https://api.github.com/repos/coderwin/__/issues/23/comments","events_url":"https://api.github.com/repos/coderwin/__/issues/23/events","html_url":"https://github.com/coderwin/__/issues/23","id":309984985,"number":23,"title":"Tapable API 文档及使用教程","user":{"login":"coderwin","id":8546902,"avatar_url":"https://avatars2.githubusercontent.com/u/8546902?v=4","gravatar_id":"","url":"https://api.github.com/users/coderwin","html_url":"https://github.com/coderwin","followers_url":"https://api.github.com/users/coderwin/followers","following_url":"https://api.github.com/users/coderwin/following{/other_user}","gists_url":"https://api.github.com/users/coderwin/gists{/gist_id}","starred_url":"https://api.github.com/users/coderwin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/coderwin/subscriptions","organizations_url":"https://api.github.com/users/coderwin/orgs","repos_url":"https://api.github.com/users/coderwin/repos","events_url":"https://api.github.com/users/coderwin/events{/privacy}","received_events_url":"https://api.github.com/users/coderwin/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-03-30T06:12:31Z","updated_at":"2018-03-30T06:12:31Z","closed_at":null,"author_association":"OWNER","body":"# Tapable API 文档及使用教程\r\n## Tapable（0.2.x）\r\n### 使用\r\n\r\n```\r\nimport Tapable from 'tapable';\r\n//var Tapable = require('tapable');\r\n```\r\nTapable 是一个用于事件发布订阅执行的插件架构。\r\n在使用时你仅仅需要像这样继承它：\r\n\r\n```\r\nfunction MyClass() {\r\n  Tapable.call(this);\r\n}\r\nMyClass.prototype = Object.create(Tapable.prototype);\r\n\r\n// 或者这样\r\nfunction MyClass2() {\r\n  Tapable.call(this);\r\n}\r\nTapable.mixin(MyClass2.prototype);\r\n\r\n// 或者这样\r\nclass MyClass3 extends Tapable {\r\n  constructor() {\r\n    // TODO\r\n  }\r\n}\r\n```\r\n### API\r\n#### 静态方法（Static functions）\r\n* mixin\r\n\r\n```\r\nvoid mixin(obj: Object)\r\n```\r\n复制 Tapable 的原型方法到目标对象\r\n\r\n#### 实例公共方法（Public functions）\r\n* apply\r\n\r\n> 插件加载函数\r\n\r\n```\r\nvoid apply(plugin1: Plugin, plugin2: Plugin...)\r\n```\r\n通过 arguments 获得所有传入的插件对象，并调用插件对象的 apply 方法，注册插件（所以，一个合法的插件应该包含入口方法 apply）\r\n\r\n* plugin\r\n\r\n> 事件绑定函数，类似于 EventEmitter 的 on 方法\r\n\r\n```\r\nvoid plugin(names: string|string[], handler: Function)\r\n```\r\nnames: 需要监听的事件名称，可以传入事件名称集合（同时绑定多个事件），也可以传入单个事件名称\r\nhandler: 事件的处理函数\r\n\r\n例子1：\r\n\r\n```\r\nvar Tapable = require('tapable');\r\n\r\nfunction Compiler(plugins) {\r\n  Tapable.call(this);\r\n  // 注册插件\r\n  this.apply(...plugins);\r\n  // 编译器在某个异步操作完成后触发事件\r\n  setTimeout(() => {\r\n    // 触发事件\r\n    this.applyPlugins('compiled', 'test');\r\n  }, 4000);\r\n}\r\nCompiler.prototype = Object.create(Tapable.prototype);\r\n\r\nfunction CustomPlugin() {}\r\nCustomPlugin.prototype.apply = function (compiler) {\r\n  // 注册插件时会调用插件的 apply 方法，会执行绑定插件\r\n  compiler.plugin('compiled', (arg) => {\r\n    console.log('arg:', arg); // arg: test\r\n  });\r\n};\r\n\r\nnew Compiler([new CustomPlugin()]);\r\n```\r\n\r\n#### 实例受保护方法（Protected functions）\r\n\r\n* applyPlugins\r\n\r\n> 类似 EventEmitter 的 emit 方法，使用实例见例子1\r\n\r\n```\r\nvoid applyPlugins(name: string, args: any...)\r\n```\r\n触发事件 name，传入参数 args，并行调用所有注册在事件 name 上的处理函数。\r\n\r\n* applyPluginsWaterfall\r\n\r\n```\r\nany applyPluginsWaterfall(name: string, init: any, args: any...)\r\n```\r\n触发事件 name，串行的调用注册在事件 name 上的处理函数（先入先出），最先执行的处理函数传入 init 和 args，后续的处理函数传入前一个处理函数的返回值和 args，函数最终返回最后一个处理函数的返回结果\r\n例子2：【后面的例子可以由这个例子修改观察结果】\r\n\r\n```\r\nvar Tapable = require('tapable');\r\n\r\nfunction Compiler(plugins) {\r\n  Tapable.call(this);\r\n  // 注册插件\r\n  this.apply(...plugins);\r\n  // 编译器在某个异步操作完成后触发事件\r\n  setTimeout(() => {\r\n    // 触发事件\r\n    const afterPluginValue = this.applyPluginsWaterfall('compiled', 'InitValue');\r\n    console.log('after all plugins value:', afterPluginValue);\r\n  }, 4000);\r\n}\r\nCompiler.prototype = Object.create(Tapable.prototype);\r\n\r\nfunction CustomPlugin() {}\r\nCustomPlugin.prototype.apply = function (compiler) {\r\n  // 注册插件时会调用插件的 apply 方法，会执行绑定插件\r\n  compiler.plugin('compiled', (arg) => {\r\n    console.log('in plugin value:', arg);\r\n    // todo\r\n    console.log('out plugin value:', 'PluginValue');\r\n    return 'PluginValue';\r\n  });\r\n};\r\nfunction CustomPlugin1() {}\r\nCustomPlugin1.prototype.apply = function (compiler) {\r\n  // 注册插件时会调用插件的 apply 方法，会执行绑定插件\r\n  compiler.plugin('compiled', (arg) => {\r\n    console.log('in plugin1 value::', arg);\r\n    // todo\r\n    console.log('out plugin1 value:', 'PluginValue1');\r\n    return 'Plugin1Value';\r\n  });\r\n};\r\n\r\nnew Compiler([new CustomPlugin(), new CustomPlugin1()]);\r\n\r\n// in plugin value: InitValue\r\n// out plugin value: PluginValue\r\n// in plugin1 value:: PluginValue\r\n// out plugin1 value: PluginValue1\r\n// after all plugins value: Plugin1Value\r\n```\r\n\r\n* applyPluginsAsyncWaterfall\r\n\r\n```\r\napplyPluginsAsyncWaterfall(\r\n  name: string,\r\n  init: any,\r\n  callback: (err: Error, result: any) -> void\r\n)\r\n```\r\n触发事件 name，串行的调用注册在 name 上的处理函数(先入先出)，第一个处理函数传入参数 init，后续的函数依赖于前一个函数执行回调的时候传入的参数nextValue，倘若某一个处理函数报错，则执行传入的 callback(err)，后续的处理函数将不被执行，否则最后一个处理函数调用 callback(value)\r\n注意：插件注册此类事件，处理函数需要调用 callback(err, nextValue)，这样才能保证监听链的正确执行\r\n\r\n```\r\nvar myPlugin = function() {}\r\nmyPlugin.prototype.apply(tapable) {\r\n  tapable.plugin('name', function(arg1, ..., argn, callback)) {\r\n    // todo\r\n    // ...\r\n    // 调用 callback\r\n    callback(null, value);\r\n  }\r\n}\r\n```\r\n\r\n* applyPluginsAsync = applyPluginsAsyncSeries\r\n\r\n```\r\nvoid applyPluginsAsync(\r\n  name: string,\r\n  args: any...,\r\n  callback: (err?: Error) -> void\r\n)\r\n```\r\n触发事件 name，串行的调用注册在事件 name 上的处理函数（先入先出），倘若某一个处理函数报错，则执行传入的 callback(err)，后续的处理函数将不被执行，否则最后一个处理函数调用 callback。\r\n注意：插件注册此类事件，处理函数需要调用callback，这样才能保证监听链的正确执行\r\n\r\n```\r\nvar myPlugin = function() {}\r\nmyPlugin.prototype.apply(tapable) {\r\n  tapable.plugin('name', function(arg1, ..., argn, callback)) {\r\n    // todo\r\n    // ...\r\n    // 调用callback\r\n    callback();\r\n  }\r\n}\r\n```\r\n\r\n* applyPluginsBailResult\r\n\r\n```\r\nany applyPluginsBailResult(name: string, args: any...)\r\n```\r\n触发事件 name，串行的调用注册在事件 name 上的处理函数（先入先出），传入参数 args，如果其中一个处理函数返回值 !== undefined，直接返回这个返回值，后续的处理函数将不被执行\r\n\r\n* applyPluginsParallel\r\n\r\n```\r\napplyPluginsParallel(\r\n  name: string,\r\n  args: any...,\r\n  callback: (err?: Error) -> void\r\n)\r\n```\r\n触发事件 name，传入参数 args，并行的调用所有注册在事件 name 上的处理函数，倘若任一处理函数执行报错，则执行 callback('err')，否则当所有的处理函数都执行完的时候调用 callback()\r\n\r\n同样，插件注册此类事件的时候，回调函数要执行 callback\r\n\r\n\r\n* applyPluginsParallelBailResult\r\n\r\n```\r\napplyPluginsParallelBailResult(\r\n  name: string,\r\n  args: any...,\r\n  callback: (err: Error, result: any) -> void\r\n)\r\n```\r\n触发事件 name，串行的执行注册在事件 name 上的处理函数（先入先出），每个处理函数必须调用 callback(err, result)，倘若任一处理函数在调用callback(err, result) 的时候，err !== undefined || result !== undefined，则 callback 将真正被执行，后续的处理函数则不会再被执行。"}}
{"actor":{"display_login":"coderwin"}}