Skip to content

Read-Eval-Print-Loop(REPL)

REPL 是一个简单的交互式环境,它会接收单次用户输入、执行该输入,并将结果返回给用户。 REPL 功能允许你检查依赖图,并且可以直接在终端中调用 provider(以及 controller)上的方法。

用法

要以 REPL 模式运行你的 NestJS 应用,请新建一个 repl.ts 文件(与现有的 main.ts 文件并列),并在其中添加以下代码:

typescript
// repl.ts
import { repl } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  await repl(AppModule);
}
bootstrap();

现在,在终端中使用以下命令启动 REPL:

bash
$ npm run start -- --entryFile repl

提示

repl 会返回一个 Node.js REPL server 对象。

当它启动完成后,你应该会在控制台中看到如下信息:

bash
LOG [NestFactory] Starting Nest application...
LOG [InstanceLoader] AppModule dependencies initialized
LOG REPL initialized

现在你就可以开始与依赖图交互了。例如,你可以获取一个 AppService(这里以 starter 项目为例),并调用 getHello() 方法:

typescript
> get(AppService).getHello()
'Hello World!'

你也可以直接在终端中执行任意 JavaScript 代码,例如,把 AppController 的实例赋值给一个局部变量,并使用 await 调用异步方法:

typescript
> appController = get(AppController)
AppController { appService: AppService {} }
> await appController.getHello()
'Hello World!'

要显示某个 provider 或 controller 上所有可用的公共方法,请使用 methods() 函数,如下所示:

typescript
> methods(AppController)

Methods:
 ◻ getHello

要打印所有已注册模块,以及它们的控制器和提供者列表,请使用 debug()

typescript
> debug()

AppModule:
 - controllers:
  ◻ AppController
 - providers:
  ◻ AppService

快速演示:

REPL example

关于现有内置原生方法的更多信息,请参见下方章节。

原生函数

NestJS 内置 REPL 提供了一些原生函数,在你启动 REPL 后它们会以全局方式可用。你可以调用 help() 来列出它们。

如果你不记得某个函数的签名(即参数和返回类型),可以调用 <function_name>.help。 例如:

text
> $.help
Retrieves an instance of either injectable or controller, otherwise, throws exception.
Interface: $(token: InjectionToken) => any

提示

这些函数接口使用的是 TypeScript function type expression 语法

函数说明签名
debug打印所有已注册模块及其控制器和提供者列表。debug(moduleCls?: ClassRef | string) => void
get$获取某个 injectable 或 controller 的实例,否则抛出异常。get(token: InjectionToken) => any
methods显示某个 provider 或 controller 上所有可用的公共方法。methods(token: ClassRef | string) => void
resolve解析某个瞬态或请求作用域的 injectable 或 controller 实例,否则抛错。resolve(token: InjectionToken, contextId: any) => Promise<any>
select允许在模块树中导航,例如从选中的模块中获取某个特定实例。select(token: DynamicModule | ClassRef) => INestApplicationContext

监听模式

在开发过程中,以 watch 模式运行 REPL 会很有用,因为它可以自动反映所有代码变更:

bash
$ npm run start -- --watch --entryFile repl

不过这有一个缺点:每次重新加载之后,REPL 的命令历史都会被丢弃,这会比较麻烦。 幸运的是,解决方法非常简单。把你的 bootstrap 函数改成这样:

typescript
async function bootstrap() {
  const replServer = await repl(AppModule);
  replServer.setupHistory(".nestjs_repl_history", (err) => {
    if (err) {
      console.error(err);
    }
  });
}

这样一来,历史记录就会在多次运行/重载之间保留下来。

基于 NestJS 官方文档翻译