ジェネレーターを作成する際に理解すべき最も重要な概念の 1 つは、メソッドがどのように実行され、どのコンテキストで実行されるかです。
アクションとしてのプロトタイプメソッド
ジェネレーターのプロトタイプに直接アタッチされた各メソッドは、タスクとみなされます。各タスクは、Yeoman 環境の実行ループによって順次実行されます。
言い換えれば、Object.getPrototypeOf(Generator)
によって返されるオブジェクト上の各関数は、自動的に実行されます。
ヘルパーメソッドとプライベートメソッド
プロトタイプメソッドがタスクとみなされることがわかったので、自動的に呼び出されないヘルパーメソッドやプライベートメソッドをどのように定義するのか疑問に思うかもしれません。これを実現するには、3 つの異なる方法があります。
メソッド名の先頭にアンダースコアを付ける (例:
_private_method
)。class extends Generator { method1() { console.log('hey 1'); } _private_method() { console.log('private hey'); } }
インスタンスメソッドを使用する
class extends Generator { constructor(args, opts) { // Calling the super constructor is important so our generator is correctly set up super(args, opts) this.helperMethod = function () { console.log('won\'t be called automatically'); }; } }
親ジェネレーターを拡張する
class MyBase extends Generator { helper() { console.log('methods on the parent generator won\'t be called automatically'); } } module.exports = class extends MyBase { exec() { this.helper(); } };
実行ループ
単一のジェネレーターの場合、タスクを順次実行することは問題ありません。しかし、ジェネレーターを一緒に構成し始めると、それだけでは十分ではありません。
そのため、Yeoman は 実行ループ を使用します。
実行ループは、優先度サポートを備えたキューシステムです。実行ループを処理するために、Grouped-queue モジュールを使用しています。
優先度は、コード内で特別なプロトタイプメソッド名として定義されます。メソッド名が優先度名と同じ場合、実行ループはメソッドをこの特別なキューにプッシュします。メソッド名が優先度と一致しない場合、default
グループにプッシュされます。
コードでは、次のようになります。
class extends Generator {
priorityName() {}
}
また、単一のメソッドの代わりにハッシュを使用することで、複数のメソッドをグループ化して、キュー内で一緒に実行することもできます。
Generator.extend({
priorityName: {
method() {},
method2() {}
}
});
(この最後のテクニックは、JS の class
定義とうまく連携しないことに注意してください)
利用可能な優先度は (実行順に) 次のとおりです。
initializing
- 初期化メソッド (現在のプロジェクトの状態の確認、設定の取得など)prompting
- ユーザーにオプションをプロンプトする場所 (this.prompt()
を呼び出す場所)configuring
- 設定を保存し、プロジェクトを構成する (.editorconfig
ファイルやその他のメタデータファイルを作成する)default
- メソッド名が優先度と一致しない場合、このグループにプッシュされます。writing
- ジェネレーター固有のファイル (ルート、コントローラーなど) を書き込む場所conflicts
- コンフリクトが処理される場所 (内部で使用)install
- インストールが実行される場所 (npm, bower)end
- 最後に呼び出され、クリーンアップ、さよなら など
これらの優先度ガイドラインに従うと、ジェネレーターは他のものとうまく連携できます。
非同期タスク
タスクが非同期的に作業を完了するまで実行ループを一時停止するには、複数の方法があります。
最も簡単な方法は、Promise を返すことです。Promise が解決するとループが続行されます。または、失敗した場合は例外が発生して停止します。
依存している非同期 API が Promise をサポートしていない場合は、従来の this.async()
の方法に頼ることができます。this.async()
を呼び出すと、タスクが完了したら呼び出す関数が返されます。例:
asyncTask() {
var done = this.async();
getUserEmail(function (err, name) {
done(err);
});
}
done
関数がエラーパラメーター付きで呼び出された場合、実行ループは停止し、例外が発生します。
ここからどこへ進む?
yeoman の実行コンテキストについて少し理解できたので、ユーザーインタラクション を読んで先に進むことができます。