Skip to content

独立应用

Nest 应用有多种挂载方式。你可以创建一个 Web 应用、一个微服务,或者仅仅创建一个裸的 Nest 独立应用(不带任何网络监听器)。Nest 独立应用本质上是对 Nest IoC 容器的一层包装,而这个容器中持有所有已实例化的类。借助独立应用对象,我们可以直接从任何已导入模块中拿到任意现有实例的引用。因此,你可以在任何场景下使用 Nest 框架,例如脚本化的 CRON 任务,甚至还可以在其之上构建 CLI

入门

要创建一个 Nest 独立应用,可以使用如下写法:

typescript
async function bootstrap() {
  const app = await NestFactory.createApplicationContext(AppModule);
  // 在这里编写你的应用逻辑...
}
bootstrap();

从静态模块中获取 provider

独立应用对象允许你获取 Nest 应用中注册的任意实例引用。假设 AppModule 导入了 TasksModule,而 TasksModule 中有一个 TasksService provider。这个类提供了一组我们希望在 CRON 任务中调用的方法。

typescript
const tasksService = app.get(TasksService);

我们使用 get() 方法来访问 TasksService 实例。get() 方法就像一个查询器,它会在所有已注册模块中搜索实例。你可以给它传入任意 provider token。

或者,如果你希望做严格上下文检查,也可以传入 { strict: true } 选项对象。启用该选项后,你需要先导航到具体模块,再从该模块上下文中获取所需实例。

typescript
const tasksService = app.select(TasksModule).get(TasksService, { strict: true });

下面是独立应用对象上可用于获取实例引用的方法摘要:

get()获取应用上下文中可用的 controller 或 provider 实例(包括 guards、filters 等)。
select()在模块图中导航,选中某个特定模块的上下文,再进一步提取其中的实例(通常与严格模式搭配使用)。

提示

在非严格模式下,默认选中的是根模块。如果你要定位其他模块,就需要手动沿着模块图逐步导航。

需要注意的是,独立应用没有任何网络监听器,因此所有与 HTTP 相关的 Nest 特性(例如 middleware、interceptors、pipes、guards 等)在这个上下文中都不可用。

例如,即使你在应用中注册了全局拦截器,然后通过 app.get() 拿到某个 controller 的实例,这个拦截器也不会执行。

从动态模块中获取 provider

当你处理的是动态模块时,应当把与应用中注册时完全相同的动态模块对象传给 app.select()。例如:

typescript
export const dynamicConfigModule = ConfigModule.register({ folder: './config' });

@Module({
  imports: [dynamicConfigModule],
})
export class AppModule {}

之后你就可以这样选中该模块:

typescript
const configService = app
  .select(dynamicConfigModule)
  .get(ConfigService, { strict: true });

终止阶段

如果你希望脚本执行结束后关闭 Node 应用(例如执行 CRON 任务的脚本),你必须在 bootstrap 函数末尾显式调用 app.close()

typescript
async function bootstrap() {
  const app = await NestFactory.createApplicationContext(AppModule);
  // 应用逻辑...
  await app.close();
}
bootstrap();

正如生命周期事件章节中提到的那样,这会触发生命周期钩子。

示例

一个可运行的示例可见这里

基于 NestJS 官方文档翻译