编写自己的Yeoman生成器-2.运行时上下文

编写生成器时要掌握的最重要的概念之一是方法的运行方式和上下文。

原型方法作为动作

直接附加到Generator原型的每个方法都被认为是一项任务。每个任务都由Yeoman环境运行循环按顺序运行。

换句话说,返回的对象上的每个函数Object.getPrototypeOf(Generator)都将自动运行。

辅助方法和私有方法

既然您知道原型方法被认为是一项任务,您可能想知道如何定义不会自动调用的辅助方法或私有方法。有三种不同的方法可以实现这一目标。

  1. 方法名称下划线前缀(例如_private_method)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    class extends Generator {
    method1() {
    console.log('hey 1');
    }

    _private_method() {
    console.log('private hey');
    }
    }
  2. 使用实例方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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');
    };
    }
    }
  3. 扩展父生成器:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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();
    }
    };

RunLoop

如果有一个生成器,顺序运行任务就没问题。但是,一旦你开始组合生成器,这还不够。

这就是Yeoman使用RunLoop的原因。

RunLoop是具有优先级支持的队列系统。我们使用Grouped-queue模块来处理RunLoop。

优先级在您的代码中定义为特殊原型方法名称。当方法名称与优先级名称相同时,运行循环将方法推入此特殊队列。如果方法名称与优先级不匹配,则将其推送到default组中。

在代码中,它将看起来像这样:

1
2
3
class extends Generator {
priorityName() {}
}

您还可以使用哈希而不是单个方法将多个方法组合在队列中:

1
2
3
4
5
6
Generator.extend({
priorityName: {
method() {},
method2() {}
}
});

(注意,最后一种技术不适合JS class定义)

可用的优先级是(按运行顺序):

  1. initializing - 您的初始化方法(检查当前项目状态,获取配置等)
  2. prompting - 提示用户选择的地方(你打电话的地方this.prompt())
  3. configuring- 保存配置并配置项目(创建.editorconfig文件和其他元数据文件)
  4. default - 如果方法名称与优先级不匹配,则会将其推送到该组。
  5. writing- 编写生成器特定文件(路由,控制器等)的位置
  6. conflicts - 处理冲突的地方(内部使用)
  7. install- 安装运行的地方(npm,yarn)
  8. end- 最后称呼,清理,说再见等

遵循这些优先级指南,您的生成器将与其他人一起玩。

异步任务

有多种方法可以暂停RunLoop,直到任务完成异步工作。

最简单的方法是返回一个Promise。一旦Promise解析,循环将继续,或者它将引发异常并在失败时停止。

如果您所依赖的异步API不支持Promise,那么您可以依赖于遗留this.async()方式。this.async()一旦任务完成,调用将返回一个函数来调用。例如:

1
2
3
4
5
6
7
asyncTask() {
var done = this.async();

getUserEmail(function (err, name) {
done(err);
});
}

如果done使用error参数调用该函数,则运行循环将停止并引发异常。

Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2021 朝着牛逼的道路一路狂奔 All Rights Reserved.

访客数 : | 访问量 :