【问题标题】:Invoked Yeoman sub generator doesn't prompt调用 Yeoman 子生成器不提示
【发布时间】:2015-02-14 22:19:52
【问题描述】:

我想从我的主生成器中调用一些子生成器,并让它们使用提示来获取自己的信息。我当前的实现是在调用子生成器的提示步骤的同时完成主生成器的编写步骤,但我想执行以下步骤:

  1. 主发电机提示步骤
  2. 调用子生成器的提示步骤
  3. 编写主生成器的步骤
  4. 调用子生成器的编写步骤

我的主生成器如下所示:

'use strict';
var yeoman = require('yeoman-generator');
var chalk = require('chalk');
var yosay = require('yosay');

module.exports = yeoman.generators.Base.extend({
  initializing: function () {
    this.pkg = require('../package.json');
  },

  prompting: function () {
    var done = this.async();

    // Have Yeoman greet the user.
    this.log(yosay(
      'Welcome to the neat ' + chalk.red('DockerSetup') + ' generator!'
    ));

    // Check for usage of redis, postgres and mysql subgenerators
    this.prompt([
    {
      type: 'input',
      name: 'subApplications',
      message: 'Enter the names of the sub-apps comma seperated'
    }], function (props) {
      this.subApplications = props.subApplications.length ? props.subApplications.split(',') : [];


    // Run subgenerators

    this.subApplications.forEach(function(name) {
      this.composeWith('docker-setup:sub-application', { args: [name] });
    }.bind(this));

      done();
    }.bind(this));
  },

  writing: function () {
    this.fs.copyTpl(
      this.templatePath('_Readme.md'),
      this.destinationPath('Readme.md')
    );
  }
});

这是我的子生成器

'use strict';
var yeoman = require('yeoman-generator');

module.exports = yeoman.generators.NamedBase.extend({
  initializing: function () {
    this.log('You called the DockerSetup subgenerator with the argument ' + this.name + '.');
  },

  prompting: function () {
    // Assume that the sub-apps are one level under this with same name

    this.prompt([
    {
      type: 'list',
      name: 'mainTech',
      message: 'Which is the main technology used?',
      choices: ['rails', 'yii', 'frontend']
    }, {
      type: 'checkbox',
      name: 'additionalTechnologies',
      message: 'Which technologies are used in this subapp?',
      choices: ['redis', 'postgres', 'mysql']
    }], function (props) {
      this.mainTech = props.mainTech;
      this.additionalTechnologies = props.additionalTechnologies;


      // This is done here, because if it's in the writing part it gets called before the prompt
      var path = this.destinationPath('fig.yml'),
          file = this.readFileAsString(path),
          content;

      switch(this.mainTech) {
        case 'rails':
          content = 'content';
        break;

        case 'yii':
        break;

        case 'frontend':
        break;
      }

      this.additionalTechnologies.forEach(function (tech) {
        content += ('    - ' + tech);
      });

      file += content;
      this.write(path, file);

      done();
    }.bind(this));
  }
});

【问题讨论】:

    标签: javascript node.js yeoman yeoman-generator


    【解决方案1】:

    在您真正完成该子生成器中的提示之前,您不应该调用done() 函数。事实上,在将工作分派给子生成器之后,您可以继续执行。相反,您应该只异步调用done()(因为它是大多数时间使用异步/完成的用例)。

    为此,我相信您可以像这样将composeWith 命令与.on 链接起来:

    this.subApplications.forEach(function(name) {
          this.composeWith('docker-setup:sub-application', { args: [name] })
              .on('end',function(){
                            done();
                        });
        }.bind(this));
    

    'end' 事件在每个 yo 进程结束时发出,根据 base.js 第 358 行)

    【讨论】:

    • 你知道返回值的接口是什么吗?
    • 返回值究竟是什么?
    • this.composeWith(...)
    • 遗憾的是,我不知道任何用于从子生成器返回值的内置通道。根据上面的源链接,emit 调用可以采用除“end”之外的附加参数,但似乎没有使用。
    • 大多数情况下,架构可以重新设计为不需要来自子生成器的返回值。我相信子生成器应该被认为是独立的构建块,它们也可以自己调用,这使得这种依赖于其他子生成器“输出”的用例有点不寻常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-11
    • 2014-01-10
    • 1970-01-01
    • 2018-07-18
    • 1970-01-01
    相关资源
    最近更新 更多