Yeoman生成器完成后,同步执行命令行操作

时间:2014-07-03 10:10:37

标签: javascript node.js yeoman

我正在构建一个Yeoman生成器,在它完成后我想执行一些命令行操作,如'npm install','bower install'和'grunt less'。我正在使用spawnCommand,并使用事件侦听器嵌套所有操作以同步执行它们。但是,为了避免这种无休止的嵌套,我正在寻找更清晰的实现,以使其易于扩展。 完美的说,我想有一个带有命令的数组(比如['npm install','grunt install','less:dev'])并且通过正确的错误检测同步处理。

// Install npm packages
this.spawnCommand('npm', ['install'])
    .on('exit', function (err) {
        if (err) {
            this.log.error('npm package installation failed. Please run \'npm install\' and \'bower install\'. Error: ' + err);
        } else {
            // Install bower packages
            this.spawnCommand('bower', ['install'])
                .on('exit', function (err) {
                    if (err) {
                        this.log.error('bower package installation failed. Please run \'bower install\'. Error: ' + err);
                    } else {
                        this.spawnCommand('grunt', ['less'])
                            .on('exit', function (err) {
                                if (err) {
                                    this.log.error('Less compilation failed. Please run \'grunt less:dev\'. Error: ' + err);
                                } else {

                                }

                            }.bind(this));
                    }

                }.bind(this));
        }

    }.bind(this));

3 个答案:

答案 0 :(得分:2)

这样的东西? (虽然未经测试):

this.processTask = function (task) {
    this.spawnCommand(task.cmd, task.args)
        .on('exit', function (err) {
            if (err) {
                this.log.error('task failed. Error: ' + err);
            } else {
                this.emit('nextTask');
            }
        });
};

this.on('nextTask' function(){
    var next = this.tasks.shift();
    if (next){
       this.processTask(next);
    } else {
       console.log('we are done');
    }
}.bind(this));

//preparing the list of tasks:
this.tasks = [];
this.tasks.push({cmd: 'npm', args:['install']});
this.tasks.push({cmd: 'bower', args:['install']});
this.tasks.push({cmd: 'grunt', args:['less']});

//start first task

this.processTask(this.tasks.shift());

答案 1 :(得分:0)

我使用了来自Node.js的execSync,它似乎有效,例如:

var child_process = require('child_process');

var result = execSync('grunt less');

Node.js 0.12和io.js 1.10支持execSync:

child_process.execSync(command[, options])

并返回," Buffer | String命令"中的stdout,可能是错误代码。 API documentation.

The back story about the synchronous API

答案 2 :(得分:0)

您可以创建一个类似init.sh的脚本,并将需要按顺序运行的命令放入其中,例如:

#!/usr/bin/env bash
npm install
your-funky-command
gulp something-special
gulp

...然后,只要您需要放置spawnCommand代码(我在end方法中执行此操作),请添加以下内容:

  var done = this.async();
  this.spawnCommand('sh', ['init.sh'], /* maybe cwd? {cwd: 'src'} */)
    .on('close', done);

不漂亮或任何东西,但它有效,而且很明显。

或者,如果您需要一个命令仅在prev成功时运行,请执行以下操作:

#!/usr/bin/env bash
npm install \
  && your-funky-command \
  && gulp something-special \
  && gulp

(额外优势在于,现在你的应用初始逻辑不再与Yo绑定。)