背景
我正在为 Angular SPA(单页应用程序)创建一个脚手架生成器。它将依赖于标准角度生成器(“yo Angular”)设置的环境,并且还依赖于标准角度子生成器来生成应用程序所需的一些额外服务和 Controller 。换句话说,我正在“装饰”一个基本的角度应用程序。
如果用户之前安装了角度应用程序,则生成器将正常工作(我查找标记文件并在代码中设置 bool 值“angularAppFound”)。但是,我希望它也是“一站式”,因为如果他们没有设置角度应用程序,我的生成器将在我安装额外的角度工件之前为他们调用角度生成器在一次运行内。
显然,如果角度应用程序没有到位,我的依赖任务将无法工作。
数据
我的代码如下所示:
// need this to complete before running other task
subgeneratorsApp: function () {
if (!this.angularAppFound) {
var done = this.async();
this.log('now creating base Angular app...');
// doesn't work (does not drive .on)
//this.composeWith('angular', {args: [ this.appName ]} )
// works (drives .on)
this.invoke('angular', {args: [ this.appName ]} )
.on('end',function(){
this.log('>>>in end handler of angular base install');
done();
}.bind(this));
}
},
// additional steps to only run after full angular install
subgeneratorServices: function () {
Object.keys(this.artifacts.services).forEach( function (key, index, array) {
this.composeWith('angular:service', {args: [ this.artifacts.services[key] ]} );
}.bind(this));
},
subgeneratorControllers: function () {
Object.keys(this.artifacts.controllers).forEach( function (key, index, array) {
this.composeWith('angular:controller', {args: [ this.artifacts.controllers[key] ]} );
}.bind(this));
},
通过查看日志和结果,我凭经验确定“composeWith”不会驱动 .on 方法,而“invoke”则驱动。
如果不驱动.on方法,则不驱动done(),并且生成器在角度基础安装后停止,并且不驱动后续步骤(因为生成器认为该步骤永远不会完成)。
我可以很好地使用调用,但它已被弃用:
(!) generator#invoke() is deprecated. Use generator#composeWith() - see http://yeoman.io/authoring/composability.html
问题
When composing generators, the core idea is to keep both decoupled. They shouldn't care about the ordering, they should run in any order and output the same result.
既然排序很重要(除了使用“invoke”),那么我应该如何处理我的情况?我想不出任何其他方法可以在不牺牲“一站式”处理的情况下重新组织我的生成器。
我是否应该简单地说用户必须在单独的步骤中安装角度并且不允许“一站式”处理?
“composeWith”不发出“end”事件是设计使然吗?
如果没有,您是否建议我打开错误报告,或者是否有其他方法可以做到这一点(未弃用)?
非常感谢。
最佳答案
生成器的可组合性使用 priority base run loop 来排序。 。因此,在运行您的生成器之前,可以等待另一个生成器完成。
虽然这里棘手的部分是,一旦触发结束事件,生成器就完成运行。它不会安排任何 future 的任务 - end
事件意味着一切都已完成,是时候结束了。公平地说,您不应该需要结束事件。它仍然位于 Yeoman 中,只是为了向后兼容。
就您而言,您需要两个发电机。 app
生成器(根生成器)和您的自定义功能生成器。然后你将它们组合在一起:
因此,在 generator/app/index.js
中,您将按如下方式组织代码:
writing: {
this.composeWith('angular:app');
},
end: function () {
this.composeWith('my:subgen');
}
生成器角度巨大且相当复杂。它仍然基于旧版本的 Yeoman,这意味着将它用作基础生成器可能会更困难。我相信项目的所有者会很高兴获得一些帮助来升级和改进构图故事。 - 如果您想知道 Yeoman 组合的更好的开发人员 UX 是什么样子,请查看 generator-node他们被设计为合成的基础生成器。
关于node.js - yeoman 生成器中的 ComposeWith 不发出结束事件,因此不驱动 'on' 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33010498/