【问题标题】:Yeoman generator: how to run async command after all files copiedYeoman 生成器:复制所有文件后如何运行异步命令
【发布时间】:2015-03-03 17:43:30
【问题描述】:

我正在编写一个 yeoman 生成器。 复制所有文件后,我需要运行一些 shell 脚本。 生成器被称为子生成器,因此它应该等到脚本完成。
该脚本是通过spawn运行的一些命令文件:

that.spawnCommand('createdb.cmd');

由于脚本依赖于生成器创建的文件,因此它无法在生成器的方法中直接运行,因为所有复制/模板操作都是异步的并且尚未执行:

MyGenerator.prototype.serverApp = function serverApp() {
  if (this.useLocalDb) {
    this.copy('App_Data/createdb.cmd', 'App_Data/createdb.cmd');
    // here I cannot run spawn with createdb.cmd as it doesn't exist
  }
}

所以我找到的唯一可以运行 spawn 的地方是 'end' 事件处理程序:

var MyGenerator = module.exports = function MyGenerator (args, options, config) {
  this.on('end', function () {
    if (that.useLocalDb) {
      that.spawnCommand('createdb.cmd')
    }
  }
}

脚本成功运行,但生成器比子进程更早完成。我需要告诉 Yeoman 等待我的子进程。 像这样的:

this.on('end', function (done) {
  this.spawnCommand('createdb.cmd')
    .on('close', function () {
      done();
    });
}.bind(this));

但是'end'处理程序没有'dine'回调的参数。

如何做到这一点?

更新
感谢@SimonBoudrias,我得到了它的工作。
完整的工作代码如下。
BTW:end 方法在docs 中有描述

var MyGenerator = module.exports = yeoman.generators.Base.extend({
    constructor: function (args, options, config) {
        yeoman.generators.Base.apply(this, arguments);
        this.appName = this.options.appName;
    },

    prompting : function () {   
        // asking user
    },

    writing : function () { 
        // copying files
    },

    end: function () {
        var that = this;
        if (this.useLocalDb) {
            var done = this.async();
            process.chdir('App_Data');

            this.spawnCommand('createdb.cmd').on('close', function () {
                that._sayGoodbay();
                done();
            });

            process.chdir('..');
        } else {
            this._sayGoodbay();
        }
    },

    _sayGoodbay: funciton () {
        // final words to user
    }
});

【问题讨论】:

    标签: node.js yeoman yeoman-generator


    【解决方案1】:

    永远不要在end 事件中触发任何操作。此事件由实现者使用,而不是生成器本身。

    在你的情况下:

    module.exports = generators.Base({
        end: function () {
            var done = this.async();
            this.spawnCommand('createdb.cmd').on('close', done);
        }
    });
    

    【讨论】:

    • 谢谢,但由于某种原因没有调用end 方法。我相信它与 ``` MyGenerator.prototype.end = function () { var done = this.async(); if (this.useLocalDb) { this.spawnCommand('createdb.cmd').on('close', done); } } ``` 对吗?
    • end 方法将被调用。您可能会通过调用this.async() 而在不调用回调的情况下在某处阻止该进程。或任何其他可以阻止进程的方式。但是该方法会被调用,只需运行我的示例代码就可以在没有您自己的代码的情况下看到它的工作原理。
    猜你喜欢
    • 2020-07-29
    • 1970-01-01
    • 2021-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-27
    • 2018-07-18
    相关资源
    最近更新 更多