如何在NestJS中为Websockets-gateway传递动态端口
问题原因
你的代码中const WS_PORT = parseInt(process.env.WS_PORT)的执行时机是代码加载阶段,早于Nest的ConfigModule初始化完成的时间点,此时ConfigModule还没有读取你指定的.env文件内容挂载到process.env上,process.env.WS_PORT为undefined,经过parseInt转换后自然为NaN。
解决方案
方案一:手动提前加载env配置(简单快速)
直接在网关文件最顶部加载dotenv读取配置,保证端口赋值前配置已经加载完成:
- 安装dotenv依赖:
npm i dotenv - 修改网关代码:
import * as dotenv from 'dotenv'; import * as path from 'path'; // 路径和你ConfigModule中配置的envFilePath保持一致 dotenv.config({ path: path.join(__dirname, './config/dev.env') }); import { WebSocketGateway } from '@nestjs/websockets'; const WS_PORT = parseInt(process.env.WS_PORT); @WebSocketGateway(WS_PORT) export class WsGateway { constructor() { console.log(WS_PORT); } }
注意使用该方案前先确认你的.env文件中确实存在WS_PORT配置项,且值为合法数字。
方案二:异步注册网关(符合Nest最佳实践)
该方案可以复用Nest的ConfigService能力,不需要手动处理env加载路径,适配多环境切换场景:
- 新增常量文件定义注入令牌:
// src/ws/ws.constants.ts export const WS_PORT_TOKEN = 'WS_PORT';
- 修改
AppModule中的provider配置,改用异步工厂创建网关实例:
@Module({ imports: [ ConfigModule.forRoot({ envFilePath: './src/config/dev.env', isGlobal: true, }), // 其余导入保持不变 ], controllers: [AppController], providers: [ { provide: WS_PORT_TOKEN, useFactory: (configService: ConfigService) => configService.get<number>('WS_PORT'), inject: [ConfigService], }, { provide: WsGateway, useFactory: (wsPort: number) => { @WebSocketGateway(wsPort) class WsGatewayImpl extends WsGateway {} return new WsGatewayImpl(); }, inject: [WS_PORT_TOKEN], }, AppService ], }) export class AppModule {}
- 原网关代码简化为:
import { WebSocketGateway } from '@nestjs/websockets'; import { Inject } from '@nestjs/common'; import { WS_PORT_TOKEN } from './ws.constants'; export class WsGateway { constructor(@Inject(WS_PORT_TOKEN) private wsPort: number) { console.log(this.wsPort); } }
内容的提问来源于stack exchange,提问作者Nowa Concordia
相关产品推荐
相关产品推荐

